#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ByteOrder.h>
#include <File.h>
#include <TranslatorFormats.h>
#include <Font.h>
#include <fs_attr.h>
#define max(x,y) ((x > y) ? x : y)
#define DATA_BUFFER_SIZE 64
struct StylesHeader {
uint32 magic;
uint32 version;
int32 count;
};
struct Style {
int32 offset;
char family[64];
char style[64];
float size;
float shear;
uint16 face;
uint8 red;
uint8 green;
uint8 blue;
uint8 alpha;
uint16 reserved;
};
void
PrintStyle(Style &style, int32 i)
{
style.offset = B_BENDIAN_TO_HOST_INT32(style.offset);
style.size = B_BENDIAN_TO_HOST_FLOAT(style.size);
style.shear = B_BENDIAN_TO_HOST_FLOAT(style.shear);
style.face = B_BENDIAN_TO_HOST_INT16(style.face);
style.reserved = B_BENDIAN_TO_HOST_INT16(style.reserved);
printf("\nStyle %d:\n", static_cast<int>(i + 1));
printf("offset: %d\n", static_cast<int>(style.offset));
printf("family: %s\n", style.family);
printf("style: %s\n", style.style);
printf("size: %f\n", style.size);
printf("shear: %f (typically 90.0)\n", style.shear);
printf("face: %u (typically 0)\n",
static_cast<unsigned int>(style.face));
printf("RGBA: (%u, %u, %u, %u)\n",
static_cast<unsigned int>(style.red),
static_cast<unsigned int>(style.blue),
static_cast<unsigned int>(style.green),
static_cast<unsigned int>(style.alpha));
printf("reserved: %u (should be 0)\n",
static_cast<unsigned int>(style.reserved));
}
bool
PrintStylesAttribute(BFile &file)
{
const char *kAttrName = "styles";
attr_info info;
if (file.GetAttrInfo(kAttrName, &info) != B_OK)
return false;
if (info.type != B_RAW_TYPE) {
printf("Error: styles attribute is of the wrong type\n");
return false;
}
if (info.size < 160) {
printf("Error: styles attribute is missing information\n");
return false;
}
uint8 *pflatRunArray = new uint8[info.size];
if (!pflatRunArray) {
printf("Error: Not enough memory available to read styles attribute\n");
return false;
}
ssize_t amtread = file.ReadAttr(kAttrName, B_RAW_TYPE, 0,
pflatRunArray, info.size);
if (amtread != info.size) {
printf("Error: Unable to read styles attribute\n");
return false;
}
StylesHeader stylesheader;
memcpy(&stylesheader, pflatRunArray, sizeof(StylesHeader));
if (swap_data(B_UINT32_TYPE, &stylesheader, sizeof(StylesHeader),
B_SWAP_BENDIAN_TO_HOST) != B_OK) {
printf("Error: Unable to swap byte order of styles header\n");
return false;
}
printf("\"styles\" attribute data:\n\n");
printf("magic number: 0x%.8lx ",
static_cast<unsigned long>(stylesheader.magic));
if (stylesheader.magic == 'Ali!')
printf("(valid)\n");
else
printf("(INVALID, should be 0x%.8lx)\n",
static_cast<unsigned long>('Ali!'));
printf("version: 0x%.8lx ",
static_cast<unsigned long>(stylesheader.version));
if (stylesheader.version == 0)
printf("(valid)\n");
else
printf("(INVALID, should be 0x%.8lx)\n", 0UL);
printf("number of styles: %d\n",
static_cast<int>(stylesheader.count));
Style *pstyle = reinterpret_cast<Style *>(pflatRunArray + sizeof(StylesHeader));
for (int32 i = 0; i < stylesheader.count; i++)
PrintStyle(*(pstyle + i), i);
delete[] pflatRunArray;
pflatRunArray = NULL;
return true;
}
bool
PrintStxtInfo(BFile &file)
{
const uint32 kstxtsize = sizeof(TranslatorStyledTextStreamHeader);
const uint32 ktxtsize = sizeof(TranslatorStyledTextTextHeader);
const uint32 kstylsize = sizeof(TranslatorStyledTextStyleHeader);
const uint32 kStyleSize = sizeof(Style);
uint8 buffer[max(max(max(kstxtsize, ktxtsize), kstylsize), kStyleSize)];
status_t nread = 0;
nread = file.Read(buffer, kstxtsize);
if (nread != static_cast<status_t>(kstxtsize)) {
printf("Error: Unable to read stream header\n");
return false;
}
TranslatorStyledTextStreamHeader stxtheader;
memcpy(&stxtheader, buffer, kstxtsize);
if (swap_data(B_UINT32_TYPE, &stxtheader, kstxtsize,
B_SWAP_BENDIAN_TO_HOST) != B_OK) {
printf("Error: Unable to swap byte order of stream header\n");
return false;
}
if (stxtheader.header.magic != B_STYLED_TEXT_FORMAT) {
printf("Styled text magic number is incorrect, aborting.\n");
return false;
}
printf("Stream Header (STXT section):\n\n");
printf("magic number: 0x%.8lx ", stxtheader.header.magic);
if (stxtheader.header.magic == B_STYLED_TEXT_FORMAT)
printf("(valid)\n");
else
printf("(INVALID, should be 0x%.8lx)\n",
static_cast<unsigned long>(B_STYLED_TEXT_FORMAT));
printf("header size: %u ",
static_cast<unsigned int>(stxtheader.header.header_size));
if (stxtheader.header.header_size == kstxtsize)
printf("(valid)\n");
else
printf("(INVALID, should be %u)\n",
static_cast<unsigned int>(kstxtsize));
printf("data size: %u ",
static_cast<unsigned int>(stxtheader.header.data_size));
if (stxtheader.header.data_size == 0)
printf("(valid)\n");
else
printf("(INVALID, should be 0)\n");
printf("version: %d ",
static_cast<int>(stxtheader.version));
if (stxtheader.version == 100)
printf("(valid)\n");
else
printf("(INVALID, should be 100)\n");
TranslatorStyledTextTextHeader txtheader;
if (file.Read(buffer, ktxtsize) != static_cast<ssize_t>(ktxtsize)) {
printf("Error: Unable to read text header\n");
return false;
}
memcpy(&txtheader, buffer, ktxtsize);
if (swap_data(B_UINT32_TYPE, &txtheader, ktxtsize,
B_SWAP_BENDIAN_TO_HOST) != B_OK) {
printf("Error: Unable to swap byte order of text header\n");
return false;
}
printf("\nText Header (TEXT section):\n\n");
printf("magic number: 0x%.8lx ", txtheader.header.magic);
if (txtheader.header.magic == 'TEXT')
printf("(valid)\n");
else
printf("(INVALID, should be 0x%.8lx)\n",
static_cast<unsigned long>('TEXT'));
printf("header size: %u ",
static_cast<unsigned int>(txtheader.header.header_size));
if (stxtheader.header.header_size == ktxtsize)
printf("(valid)\n");
else
printf("(INVALID, should be %u)\n",
static_cast<unsigned int>(ktxtsize));
printf("data size (bytes of text): %u\n",
static_cast<unsigned int>(txtheader.header.data_size));
printf("character set: %d ",
static_cast<int>(txtheader.charset));
if (txtheader.charset == B_UNICODE_UTF8)
printf("(valid)\n");
else
printf("(INVALID, should be %d)\n", B_UNICODE_UTF8);
off_t seekresult, pos;
pos = stxtheader.header.header_size +
txtheader.header.header_size +
txtheader.header.data_size;
seekresult = file.Seek(txtheader.header.data_size, SEEK_CUR);
if (seekresult < pos) {
printf("Error: Unable to seek past text data. " \
"Text data could be missing\n");
return false;
}
if (seekresult > pos) {
printf("Error: File position is beyond expected value\n");
return false;
}
ssize_t read = 0;
TranslatorStyledTextStyleHeader stylheader;
read = file.Read(buffer, kstylsize);
if (read != static_cast<ssize_t>(kstylsize) && read != 0) {
printf("Error: Unable to read entire style header\n");
return false;
}
if (read != static_cast<ssize_t>(kstylsize)) {
printf("\nFile contains no Style Header (STYL section)\n");
return false;
}
memcpy(&stylheader, buffer, kstylsize);
if (swap_data(B_UINT32_TYPE, &stylheader, kstylsize,
B_SWAP_BENDIAN_TO_HOST) != B_OK) {
printf("Error: Unable to swap byte order of style header\n");
return false;
}
printf("\nStyle Header (STYL section):\n\n");
printf("magic number: 0x%.8lx ", stylheader.header.magic);
if (stylheader.header.magic == 'STYL')
printf("(valid)\n");
else
printf("(INVALID, should be 0x%.8lx)\n",
static_cast<unsigned long>('STYL'));
printf("header size: %u ",
static_cast<unsigned int>(stylheader.header.header_size));
if (stylheader.header.header_size == kstylsize)
printf("(valid)\n");
else
printf("(INVALID, should be %u)\n",
static_cast<unsigned int>(kstylsize));
printf("data size: %u\n",
static_cast<unsigned int>(stylheader.header.data_size));
printf("apply offset: %u (usually 0)\n",
static_cast<unsigned int>(stylheader.apply_offset));
printf("apply length: %u (usually the text data size)\n",
static_cast<unsigned int>(stylheader.apply_length));
StylesHeader stylesheader;
read = file.Read(buffer, sizeof(StylesHeader));
if (read != sizeof(StylesHeader)) {
printf("Error: Unable to read Styles header\n");
return false;
}
memcpy(&stylesheader, buffer, sizeof(StylesHeader));
if (swap_data(B_UINT32_TYPE, &stylesheader, sizeof(StylesHeader),
B_SWAP_BENDIAN_TO_HOST) != B_OK) {
printf("Error: Unable to swap byte order of styles header\n");
return false;
}
printf("\nStyles Header (Ali! section):\n\n");
printf("magic number: 0x%.8lx ",
static_cast<unsigned long>(stylesheader.magic));
if (stylesheader.magic == 'Ali!')
printf("(valid)\n");
else
printf("(INVALID, should be 0x%.8lx)\n",
static_cast<unsigned long>('Ali!'));
printf("version: 0x%.8lx ",
static_cast<unsigned long>(stylesheader.version));
if (stylesheader.version == 0)
printf("(valid)\n");
else
printf("(INVALID, should be 0x%.8lx)\n", 0UL);
printf("number of styles: %d\n",
static_cast<int>(stylesheader.count));
for (int32 i = 0; i < stylesheader.count; i++) {
Style style;
read = file.Read(&style, sizeof(Style));
if (read != sizeof(Style)) {
printf("Error: Unable to read style %d\n",
static_cast<int>(i + 1));
return false;
}
PrintStyle(style, i);
}
return true;
}
int
main(int argc, char **argv)
{
printf("\n");
if (argc == 2) {
BFile file(argv[1], B_READ_ONLY);
if (file.InitCheck() != B_OK)
printf("Error opening %s\n", argv[1]);
else {
printf("Be styled text information for: %s\n\n", argv[1]);
if (PrintStylesAttribute(file) == false) {
printf("Unable to read styles attribute, attempting to read " \
"style information from file...\n\n");
PrintStxtInfo(file);
}
}
}
else {
printf("stxtinfo - reports information about a Be styled text file\n");
printf("\nUsage:\n");
printf("stxtinfo filename.stxt\n");
}
printf("\n");
return 0;
}