====== FRM Files ====== * Constant size = 1990 bytes (RBSIZ_FILE) * Offsets are 1-based, not 0-based * Little-endian format * Rather good description at http://www.clicketyclick.dk/databases/xbase/format/frm.html up to the "data structures" part * Other info from the source of the public domain DBE package at http://www.the-oasis.net/ftpmaster.php3?content=ftputils.htm * Differences noted with above reference * Files start and end with "02 00". They don't end with the array of data structures * There is no global 36-byte repeated structure but 25 12-byte Field structures and 1 24-byte Params structure, which defines, among other things, the group/subgroup expressions ===== Global structure ===== * 01-02 Version = 02 00 * 03-04 Offset: RBOFF_EXPSIZE = 3, Size: 2, contents: d2 00 = 210 (DBE: nExpSize) * 05-114 Offset: RBOFF_LENGTHS = 5, Size: RBSIZ_LENGTHS = 110, contents: 55 expression length values (DBE: cLengths) * 115-224 Offset: RBOFF_OFFSETS = 115, Size: RBSIZ_OFFSETS = 110, contents: 55 expression offset values (DBE: cOffsets) * 225-1664 Offset: RBOFF_EXPRS = 225, Size: RBSIZ_EXPRS = 1440, contents: 55 expression values (DBE: cExprs) * 1665-1964 Offset: RBOFF_FIELDS = 1665, Size: RBOFF_SIZE = 300, contents: n report fields (DBE: cFields). Different from the xbase info. * 1965-1988 Offset: RBOFF_PARAMS = 1965, Size: RBSIZ_PARAMS = 24, contents: report parameters ?. Different from the xbase info. * 1989-1990 Version = 02 00 ===== Fields ===== This is the structure of one of the 25 12-byte fields blocks, called "data structure" in the xbase description * 1-2 RBOFF_FWIDTH = 1, "Report width", Column width on report * 3-5 unused. "Pad1" and "Pad2". * 6 RBOFF_TOTAL = 6, "Total", (Y/N value). Compute a total on field * 7-8 RBOFF_FDEC = 7, "Decimal", * 9-10 RBOFF_FCONTENT = 9, "Expression content". Number of expression containing value in expression list * 11-12 RBOFF_FHEADER = 11, "Title expression no". Number of expression containint header in expression list ===== Params ===== This is the contents of the 24-byte block at RBOFF_PARAMS: * 1-2 RBOFF_PGHDR = 1, Value = 00 00 = 0 * 3-4 RBOFF_GRPEXP = 3, Value = 01 00 = 1 (DBE: aReport[RP_GROUPS][1][RG_TEXT]) * 5-6 RBOFF_SUBEPXR = 5, Value = ff ff = -1 (DBE: aReport[RP_GROUPS][2][RG_TEXT]) * 7-8 RBOFF_GRPHDR = 7, Value = 02 00 = 2 (DBE: aReport[RP_GROUPS][1][RG_HEADER]) * 9-10 RBOFF_SUBHDR = 9, Value = ff ff = -1 (DBE: aReport[RP_GROUPS][2][RG_HEADER]) * 11-12 RBOFF_PGWIDTH = 11, Value = 87 00 = 135 (DBE: aReport[RP_WIDTH]) * 13-14 RBOFF_PGLINES = 13, Value = 32 00 = 50 (DBE: aReport[RP_LINES]) * 15-16 RBOFF_LMARGIN = 15, Value = 01 00 = 1 (DBE: aReport[RP_LMARGIN]) * 17-18 RBOFF_RMARGIN = 17, Value = 01 00 = 1 (DBE: aReport[RP_RMARGIN]) * 19-20 RBOFF_COLCOUNT = 19, Value = 0a 00 = 10 (DBE: aReport[RP_COLCOUNT]) * 21 RBOFF_DBLSPACE = 21, Value = 4e = 'N' (DBE: aReport[RP_DBLSPACE]) * 22 RBOFF_SUMMARY = 22, Value = 4e = 'N' (DBE: aReport[RP_SUMMARY]) * 23 RBOFF_AEJECT = 23, Value = 4e = 'N' (DBE: aReport[RP_GROUPS][1][RG_AEJECT]) Eject between groups ? * 24 RBOFF_OPTION = 24. Contains three bit values * bit 0: (DBE: aReport[RP_BEJECT]) * bit 1: (DBE: aReport[RP_AEJECT]) * bit 2: (DBE: aReport[RP_PLAIN])