int ui;
    public void writeTOCFile(String filename, RpfHeader head, Vector frames,                             Vector groups) throws MakeTocException {        short us;        int ui;        int i, j, tail;        /*         * DKS changed from left, right for polar zone: new         * left_bottom longit.         */        double left_b, left_t, right_b, right_t, top, bottom;        double xleft, xright, ytop, ybottom;        /* !! To be filled in later */        int TOC_Nitf_hdr_size = 0; /*                                    * ?? Nitf header size for output                                    * TOC                                    */        int Loc_sec_len; /* Location section length */        int Bound_tbl_len; /* Boundary rectangle table length */        int Frame_hdr_len = 13; /* Frame index header length */        int Frame_index_rec_len = 33; /*                                       * Frame index record length                                       * (was 37)                                       */        int Frame_sec_len; /* Frame section length */        RandomAccessFile fout = null;        int groupCount = groups.size();        int nFrames = frames.size();        /* cumulative pathname positions */        int[] pathname_pos = new int[nFrames];        /* List of pathnames: directories */        String[] direct = new String[nFrames];        /* Allocations for uniq directories */        int[] uniq_dir_ptr = new int[nFrames]; /*                                                * index from filename                                                * to uniq direct.                                                */        int[] uniq_dir_pos = new int[nFrames]; /*                                                * position of direct.                                                * name in file                                                */        /* list of direct. names */        String[] uniq_dir = new String[nFrames];        String georef = "AAAAAA"; /* GEOREF # */        Frame frame;        Group group;        // Right now, just write the new file locally.        try {            fout = new RandomAccessFile(filename, "rw");            /* WRITE TOC : */            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc: *** writing TOC ***\n  at: " + filename);            }            /* HEADER SECTION */            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc: *** writing header section ***");            }            String charString;            char[] nt = new char[1];            nt[0] = '\0';            /* DKS. Can't write structure because of pad bytes */            /* fwrite(&head, sizeof(head), 1, fout); */            fout.writeBoolean(head.endian); // Big Endian - should            // match head.endian            fout.writeShort(RpfHeader.HEADER_SECTION_LENGTH);            fout.writeBytes("       A.TOC"); // has to be padded.            fout.writeByte(head.neww);            fout.writeBytes(head.standardNumber);            if (head.standardNumber.length() < 15) {                fout.writeBytes(createPadding(15 - head.standardNumber.length(),                        false));            }            fout.writeBytes(head.standardDate);            if (head.standardDate.length() < 8) {                fout.writeBytes(createPadding(8 - head.standardDate.length(),                        false));            }            // All this trouble just for a silly character.            char[] charArray = new char[1];            charArray[0] = head.classification;            charString = new String(charArray);            fout.writeBytes(charString);            Debug.message("maketoc", "MakeToc: writing country(" + head.country                    + ") and release(" + head.release + ")");            fout.writeBytes(head.country);            fout.writeBytes(head.release);            /*             * New, DKS. no longer head.loc_sec_phys_loc. Always write             * 48.             */            /*             * DFD - This isn't true, but since we don't care about             * NITF formatting, it may be. Just write out where we             * are.             */            int location_section_location = (int) fout.getFilePointer() + 4;            fout.writeInt(location_section_location);            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc: location section location is : "                        + location_section_location);            }            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc: *** writing location section ***");            }            /* LOCATION SECTION */            int Loc_hdr_len = 14; /* Location section header length */            int Loc_sec_comp_len = 10; /*                                        * Location section component                                        * length                                        */            /* 14 + 4 * 10 = 54 */            Loc_sec_len = Loc_hdr_len                    + (RpfFileSections.TOC_LOCATION_KEY * Loc_sec_comp_len);            fout.writeShort(Loc_sec_len);            /* compon. loc tbl offset: location section hdr length */            fout.writeInt(Loc_hdr_len);            /* # records in location section: 4 */            fout.writeShort(RpfFileSections.TOC_LOCATION_KEY);            /* component location record length: 10 */            fout.writeShort(Loc_sec_comp_len);            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc:\n  location section length: "                        + Loc_sec_len + "\n  location header length: "                        + Loc_hdr_len + "\n  number of location records: "                        + RpfFileSections.TOC_LOCATION_KEY                        + "\n  location section comp length: "                        + Loc_sec_comp_len);            }            /*             * compon. aggregate len: unknown here. Fill in after             * doing all else.             */            /* location component aggregate length file location */            long agg_loc = fout.getFilePointer(); /* save for later */            fout.writeInt(0); // place holder.            /* Begin: location section, component location table */            int Bound_hdr_len = 8; /* Boundary section header length */            int Bound_rec_len = 132; /* Boundary record length */            /* Boundary section length */            int Bound_sec_len = Bound_hdr_len + (groupCount * Bound_rec_len);            /* Compute frame section length, for later */            pathname_pos[0] = 0; /* cum. offset */            int uniq_dir_cnt = 0; /* # of unique directory paths. */            // Looking for the directory name for each file.            for (i = 0; i < nFrames; i++) { /* for each frame file */                /*                 * set tail to ptr to last occurrence of '/' in                 * filename                 */                /* frames[i].filename is full pathname */                frame = (Frame) frames.elementAt(i);                tail = frame.filename.lastIndexOf(File.separatorChar);                if (tail == -1) {                    direct[i] = frame.filename;                } else {                    // Java-cise the name, so it meets spec.                    direct[i] = frame.filename.substring(0, ++tail)                            .replace('\\', '/');                }                if (Debug.debugging("maketocdetail"))                    Debug.output("MakeToc: Matching directory: " + direct[i]);                /* Match direct. names with list of uniq direct. names */                /* flag for found name in list */                boolean uniq_dir_match = false;                String tmpDir = null;                if (relativeFramePaths) {                    int rpfIndex = direct[i].indexOf("RPF");                    if (rpfIndex == -1) {                        rpfIndex = direct[i].indexOf("rpf");                    }                    if (rpfIndex != -1) {                        rpfIndex += 3;                        if (direct[i].length() > rpfIndex                                && direct[i].charAt(rpfIndex) == '/') {                            rpfIndex++;                        }                        tmpDir = "./" + direct[i].substring(rpfIndex);                    } else {                        if (Debug.debugging("maketoc")) {                            Debug.output("RPF directory not found in directory path "                                    + direct[i] + ", using absolute path");                        }                        tmpDir = direct[i];                    }                } else {                    tmpDir = direct[i];                }                for (j = 0; j < uniq_dir_cnt; j++) {                    if (tmpDir.equals(uniq_dir[j])) {                        uniq_dir_ptr[i] = j;                        uniq_dir_match = true;                        if (Debug.debugging("maketocdetail"))                            Debug.output("Found match with: " + uniq_dir[j]);                        break;                    }                }                if (!uniq_dir_match) {                    uniq_dir[uniq_dir_cnt] = tmpDir;                    uniq_dir_ptr[i] = uniq_dir_cnt;                    if (Debug.debugging("maketoc"))                        Debug.output("Adding Unique directory: "                                + uniq_dir[uniq_dir_cnt]);                    uniq_dir_cnt++;                } /* if */            } /* for i */            if (Debug.debugging("maketoc"))                Debug.output("Uniq_dir_cnt: " + uniq_dir_cnt);            /* compute uniq dir pathname table length */            int path_table_len = 0;            for (j = 0; j < uniq_dir_cnt; j++) {                /* 2 for path length var. in hdr */                path_table_len += 2 + uniq_dir[j].length();            } /* for j */            /* compute directory name positions in file */            uniq_dir_pos[0] = 0;            for (j = 1; j < uniq_dir_cnt; j++) {                uniq_dir_pos[j] = uniq_dir_pos[j - 1] + 2                        + uniq_dir[j - 1].length();            } /* for j */            for (j = 0; j < uniq_dir_cnt; j++) {                if (Debug.debugging("maketocdetail"))                    Debug.output("j: " + j + ", uniq_dir_pos[j]: "                            + uniq_dir_pos[j]);            } /* for j */            /* compute direct. positions for each input file pathname */            for (i = 0; i < nFrames; i++) {                pathname_pos[i] = uniq_dir_pos[uniq_dir_ptr[i]];                if (Debug.debugging("maketocdetail"))                    Debug.output("i: " + i + ", pathname_pos[i]:"                            + pathname_pos[i]);            } /* for i */            /*             * frame file index record length: 9 + nFrames * 33 +             * path_table_len             */            Frame_sec_len = Frame_hdr_len + nFrames * Frame_index_rec_len                    + path_table_len;            /* START LOCATION RECORD 1 */            /* ID #: */            fout.writeShort((short) RpfFileSections.LOC_BOUNDARY_SECTION_SUBHEADER);            // The boundary section subheader is the first part of the            // bounfary rectangle section. The boundary section comes            // right after the header (in this program - the spec will            // allow it to be anywhere).            /* Boundary section subheader length */            fout.writeInt(Bound_hdr_len);            /* DKS. Physical location */            /* 0 + 48 + 54 */            fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH                    + Loc_sec_len);            /* START LOCATION RECORD 2 */            /* ID #: */            fout.writeShort((short) RpfFileSections.LOC_BOUNDARY_RECTANGLE_TABLE);            /* Boundary rectangle table length */            Bound_tbl_len = groupCount * Bound_rec_len;            fout.writeInt(Bound_tbl_len);            /* DKS. Physical location */            /* 0 + 48 + 54 + 8 */            fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH                    + Loc_sec_len + Bound_hdr_len);            Bound_sec_len = Bound_hdr_len + Bound_tbl_len;            /* START LOCATION RECORD 3 */            /* ID #: */            fout.writeShort((short) RpfFileSections.LOC_FRAME_FILE_INDEX_SUBHEADER);            /* length */            fout.writeInt(Frame_hdr_len);            /* physical index (offset) */            fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH                    + Loc_sec_len + Bound_sec_len);            /* START LOCATION RECORD 4 */            /* ID #: */            fout.writeShort((short) RpfFileSections.LOC_FRAME_FILE_INDEX_SUBSECTION);            /* length */            /* Frame_sec_len computed above */            fout.writeInt(Frame_sec_len - Frame_hdr_len);            /* physical index (offset) */            fout.writeInt(TOC_Nitf_hdr_size + RpfHeader.HEADER_SECTION_LENGTH                    + Loc_sec_len + Bound_sec_len + Frame_hdr_len);            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc: boundary section at : "                        + fout.getFilePointer());            }            /* START BOUNDARY RECTANGLE SECTION */            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc: *** writing boundary rectangles ***");            }            /* Subheader */            /* boundary rectangle table offset */            fout.writeInt(0);            /* # of boundary rectangle records */            fout.writeShort((short) groupCount);            /* boundary rectangle record length */            fout.writeShort((short) Bound_rec_len);            /* For each boundary rectangle record */            for (i = 0; i < groupCount; i++) {                group = (Group) groups.elementAt(i);                /*                 * Key off flag to write proper data to A.TOC for                 * browse menu later                 */                if (group.cib) {                    fout.writeBytes("CIB  ");                    fout.writeBytes("8:1  "); /* Compr. ratio */                } else if (group.cdted) {                    fout.writeBytes("CDTED");                    fout.writeBytes("6.5:1"); /*                                               * Compr. ratio:                                               * VARIABLE                                               */                } else {                    fout.writeBytes("CADRG");                    fout.writeBytes("55:1 ");                } /* else */                // Should be 12 padded chars, check just in case...                if (group.scale.length() < 12) {                    fout.writeBytes(group.scale);                    fout.writeBytes(createPadding(12 - group.scale.length(),                            false));                } else {                    fout.writeBytes(group.scale.substring(0, 12)); // Already                    // 12                    // padded                    // chars                }                // All this trouble just for a silly character.                charArray[0] = group.zone;                charString = new String(charArray);                fout.writeBytes(charString);                /* DKS changed from AFESC to DMAAC 8/2/94 */                /* Producer: */                //  Should be OpenMap BBN, I guess.                fout.writeBytes(producer);                /*                 * PBF - If group is polar, change boundaries from                 * rect coordinates to lat-lon -- 6-19-94                 */                if (group.zone == '9' || group.zone == 'J') { /*                                                               * polar                                                               * zone                                                               */                    /*                     * DKS: switched x,y to match spec: x increases                     * right, y up.                     */                    ytop = group.horiz_pos[group.top];                    ybottom = group.horiz_pos[group.bottom];                    xleft = group.vert_pos[group.left];                    xright = group.vert_pos[group.right];                    if (Debug.debugging("maketoc")) {                        Debug.output("POLAR ZONE. ytop: " + ytop                                + ", ybottom: " + ybottom + ", xleft: " + xleft                                + ", xright:" + xright);                    }                    /* see CADRG SPEC 89038, p. 50 */                    /*                     * FIND LATITUDES from x,y. x increases right, y                     * up.                     */                    /* DKS new 1/95 to handle South pole separately. */                    /* h_interval converts from pix to deg. */                    if (group.zone == '9') { /* "9": NORTH POLE */                        top = 90 - (Math.sqrt((ytop * ytop) + (xleft * xleft)) * (group.h_interval));                        bottom = 90 - (Math.sqrt((ybottom * ybottom)                                + (xright * xright)) * (group.h_interval));                    } /* North pole */                    else { /* "J": South Pole */                        top = -90                                + (Math.sqrt((ytop * ytop) + (xleft * xleft)) * (group.h_interval));                        bottom = -90                                + (Math.sqrt((ybottom * ybottom)                                        + (xright * xright)) * (group.h_interval));                    } /* South pole */                    if (Debug.debugging("maketoc"))                        Debug.output("LATS. top: " + top + ", bottom: "                                + bottom);                    /*                     * Cvt from x,y to LONGITUDE; from radians to                     * degrees                     */                    /* DKS added South pole case 1/95 */                    if (group.zone == '9') { /* "9": NORTH POLE */                        left_t = 180.0                                / Math.PI                                * Math.acos(-ytop                                        / Math.sqrt((ytop * ytop)                                                + (xleft * xleft)));                        /* DKS fixed bug 1/95: from ytop to ybottom */                        left_b = 180.0                                / Math.PI                                * Math.acos(-ybottom                                        / Math.sqrt((ybottom * ybottom)                                                + (xleft * xleft)));                        right_t = 180.0                                / Math.PI                                * Math.acos(-ytop                                        / Math.sqrt((ytop * ytop)                                                + (xright * xright)));                        /* DKS fixed bug 1/95: from ytop to ybottom */                        right_b = 180.0                                / Math.PI                                * Math.acos(-ybottom                                        / Math.sqrt((ybottom * ybottom)                                                + (xright * xright)));                    } /* if North pole */                    else { /* South Pole */                        left_t = 180.0                                / Math.PI                                * Math.acos(ytop                                        / Math.sqrt((ytop * ytop)                                                + (xleft * xleft)));                        /* DKS fixed bug 1/95: from ytop to ybottom */                        left_b = 180.0                                / Math.PI                                * Math.acos(ybottom                                        / Math.sqrt((ybottom * ybottom)                                                + (xleft * xleft)));                        right_t = 180.0                                / Math.PI                                * Math.acos(ytop                                        / Math.sqrt((ytop * ytop)                                                + (xright * xright)));                        /* DKS fixed bug 1/95: from ytop to ybottom */                        right_b = 180.0                                / Math.PI                                * Math.acos(ybottom                                        / Math.sqrt((ybottom * ybottom)                                                + (xright * xright)));                    } /* if South pole */                    /* For both poles: */                    if (xleft < 0) { /*                                      * left half of earth has                                      * negative longits                                      */                        left_t = -left_t;                        left_b = -left_b;                    }                    /* This will hardly ever happen: */                    if (xright < 0) { /*                                       * left half of earth has                                       * negative longs                                       */                        right_t = -right_t;                        right_b = -right_b;                    }                    if (Debug.debugging("maketoc"))                        Debug.output("LONGS. left_t: " + left_t + ", right_t: "                                + right_t);                    if (Debug.debugging("maketoc"))                        Debug.output("LONGS. left_b: " + left_b + ", right_b: "                                + right_b);                    //  #if 0                    //                  /* !!!!!!!!!!!!!!!!!!! Fix to getlat [80,90],                    // longit. [-180,180] */                    //                  bottom = 80.0 ;                    //                  top = 90.0 ;                    //                  left = -180.0 ;                    //                  right = 180.0 ;                    //  #endif                } /* if polar zone */                /* end DKS portion */                /* end PBF cvt from xy to lat-long */                else { /* non-polar zone */                    left_t = group.vert_pos[group.left];                    left_b = left_t;                    right_t = group.vert_pos[group.right];                    right_b = right_t;                    top = group.horiz_pos[group.top];                    bottom = group.horiz_pos[group.bottom];                } /* else */                //              Debug.output("For RpfTocEntry, writing: \n top = "                // + top +                //                           "\n bottom = " + bottom + "\n left = " + left_t +                //                           "\n right = " + right_t + "\n---------");                // Writing all doubles                fout.writeDouble(top);                fout.writeDouble(left_t);                fout.writeDouble(bottom);                fout.writeDouble(left_b);                fout.writeDouble(top);                fout.writeDouble(right_t);                fout.writeDouble(bottom);                fout.writeDouble(right_b);                fout.writeDouble(group.v_resolution);                fout.writeDouble(group.h_resolution);                fout.writeDouble(group.v_interval);                fout.writeDouble(group.h_interval);                /* # frames */                fout.writeInt((int) (group.bottom - group.top));                fout.writeInt((int) (group.right - group.left));            }            if (Debug.debugging("maketoc")) {                Debug.output("MakeToc: *** writing frame section ***");                Debug.output("MakeToc: started with a 'U'");            }            /* START FRAME SECTION */            /* Now write frames */            /* security classif */            charArray[0] = 'U';            charString = new String(charArray);            fout.writeBytes(charString);            /* frame file index tbl offset */            fout.writeInt(0);            /* # of frame file index records */            fout.writeInt(nFrames);            /* # of pathname (directory) records */            /* DKS NEW: was nFrames: */            fout.writeShort(uniq_dir_cnt);            /* frame file index record length : 33 */            fout.writeShort(Frame_index_rec_len);            /* Frame file index subsection */            for (i = 0; i < nFrames; i++) { /* for each frame file */                frame = (Frame) frames.elementAt(i);                group = (Group) groups.elementAt(frame.group);                if (!frame.marked) {                    Debug.error(frame.filename + ": not in a boundary rect??");                    //              continue;                }                /* NEW, DKS: +1 removed so range is [0,n]: */                fout.writeShort(frame.group); /* Boundary rect. rec. # */                /* Frame location ROW number */                /*                 * DKS. Changed from top to bottom to fix bug in                 * Theron's frame numbering                 */                /*                 * Should start numbering at BOTTOM (southern-most                 * part) of group                 */                /* !!! Changed back so row num is never <= 0 */                /* Alternative is bottom-y, not y-bottom. Try later */                /*                 * us = frames[i].y - groups[frames[i].group].bottom +                 * 1;                 */                /* NEW, DKS: START AT 0, NOT 1: REMOVE "+ 1": */                /* us = frames[i].y - groups[frames[i].group].top; */                /*                 * SMN The frames number are from the bottom left not                 * top left                 */                us = (short) (group.bottom - frame.y - 1);                if (Debug.debugging("maketocframedetail")) {                    Debug.output("iframe: " + i + ", frame.y: " + frame.y);                    Debug.output("frame.group: " + frame.group);                    Debug.output("group.bottom:" + group.bottom);                    Debug.output("group.top:" + group.top);                    Debug.output("frame row #:" + us);                }                fout.writeShort(us);                /* Frame location Column number */                /* NEW, DKS: START AT 0, NOT 1: REMOVE "+ 1": */                fout.writeShort((short) (frame.x - group.left));                /* pathname record offset: */                /*                 * DKS 11/10: Now w.r.t. frame file index table                 * subsection                 */                /*                 * ui = head.HEADER_SECTION_LENGTH + Loc_sec_len +                 * Bound_sec_len + Frame_hdr_len +                 * nFrames*Frame_index_rec_len + pathname_pos[i] ;                 */                fout.writeInt((int) (nFrames * Frame_index_rec_len + pathname_pos[i]));                String framename;                tail = frame.filename.lastIndexOf(File.separatorChar);                if (tail == -1) {                    framename = frame.filename;                } else {                    framename = frame.filename.substring(++tail);                }                if (framename.length() > 12) {                    Debug.error("MakeToc: encountered a frame name that's too long!\n"                            + framename);                    framename = framename.substring(0, 12);                }                /* frame file name */                fout.writeBytes(framename);                String seriesCode = framename.substring(9, 11);                /* Check for Overview image: affects GEOREF */                if (!seriesCode.equalsIgnoreCase("OV")                        && !seriesCode.equalsIgnoreCase("LG")                        && !seriesCode.equalsIgnoreCase("OI")) {                    /* Not Overview or Lengend img */                    /* DKS 8/1/94: handle polar zone separately */                    if (frame.zone != '9' || frame.zone != 'J') { /*                                                                   * polar                                                                   * zone                                                                   */                        georef = latlong2GEOREF(frame.swlat, frame.swlon);                    } else { /* not polar */                        georef = latlong2GEOREF(frame.bottom, frame.left);                    } /* else */                } else { /* Overview image has no GEOREF */                    if (Debug.debugging("maketoc"))                        Debug.output("Overview image has no GEOREF");                    georef = "000000";                } /* else */                fout.writeBytes(georef);                /* classification */                // HACK - assumes unclassified data.                fout.writeBytes(charString);                fout.writeBytes(head.country);                fout.writeBytes(head.release);            } /* for i (each frame file) */            Debug.message("maketoc",                    "MakeToc: *** writing directory section ***");            /* Pathname table */            /*             * Write UNIQUE pathnames: really Directory name, e.g.             * "./CENTRAL.USA/"             */            for (j = 0; j < uniq_dir_cnt; j++) {                /* DKS new */                /*                 * write pathname length. !!?? may be padded in front                 * to align on word bndary!!??                 */                fout.writeShort((short) (uniq_dir[j].length()));                /* pathname */                fout.writeBytes(uniq_dir[j]);            } /* for j (each uniq directory) */            /* No color table index section */            /*             * Go back and fill in component aggregate length in             * location section             */            fout.seek(agg_loc);            fout.writeInt((int) (Bound_sec_len + Frame_sec_len));            fout.close();            Debug.message("maketoc", "MakeToc: *** Normal end of make-toc ***");        } catch (IOException ioe) {            throw new MakeTocException(ioe.getMessage());        }    } /* main */