1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-05-02 00:59:37 +03:00
inform7/inter/index-module/Chapter 3/Figures Element.w

447 lines
15 KiB
OpenEdge ABL

[FiguresElement::] Figures Element.
To write the Figures element (Fi) in the index.
@ Not only figures but also sounds and external files, a little questionably.
=
void FiguresElement::render(OUTPUT_STREAM, index_session *session) {
localisation_dictionary *LD = Indexing::get_localisation(session);
inter_tree *I = Indexing::get_tree(session);
tree_inventory *inv = Indexing::get_inventory(session);
InterNodeList::array_sort(inv->figure_nodes, MakeSynopticModuleStage::module_order);
InterNodeList::array_sort(inv->sound_nodes, MakeSynopticModuleStage::module_order);
InterNodeList::array_sort(inv->file_nodes, MakeSynopticModuleStage::module_order);
@<Index the figures@>;
@<Index the sounds@>;
@<Index the internal files@>;
@<Index the files@>;
}
@h Figures.
@<Index the figures@> =
if (InterNodeList::array_len(inv->figure_nodes) <= 1) { /* cover art always creates 1 */
HTML_OPEN("p");
Localisation::roman(OUT, LD, I"Index.Elements.Fi.NoFigures");
HTML_CLOSE("p");
} else {
HTML_OPEN("p");
Localisation::bold(OUT, LD, I"Index.Elements.Fi.ListOfFigures");
HTML_CLOSE("p");
@<Tabulate the figures@>;
}
@ The table is presented with thumbnails of a given pixel width, which
the HTML renderer automatically scales to fit. Height is adjusted so as
to match this width, preserving the aspect ratio.
@d THUMBNAIL_WIDTH 80
=
@<Tabulate the figures@> =
inter_package *settings = InterPackage::from_URL(I, I"/main/completion/basics");
int MAX_INDEXED_FIGURES =
(int) Metadata::read_optional_numeric(settings, I"^max_indexed_figures");
HTML::begin_html_table(OUT, NULL, TRUE, 0, 0, 0, 0, 0);
int count_of_displayed_figures = 0;
inter_package *pack;
LOOP_OVER_INVENTORY_PACKAGES(pack, i, inv->figure_nodes) {
inter_ti id = Metadata::read_numeric(pack, I"^resource_id");
if (id > 1) {
text_stream *filename_as_text = Metadata::required_textual(pack, I"^filename");
filename *F = Filenames::from_text(filename_as_text);
TEMPORARY_TEXT(description)
unsigned int width = 0, height = 0;
int format_found = 0;
@<Find image format and dimensions@>;
@<Render a table row for the image@>;
DISCARD_TEXT(description)
}
}
HTML::end_html_table(OUT);
if (count_of_displayed_figures > MAX_INDEXED_FIGURES) {
HTML_OPEN("p");
WRITE("(");
Localisation::roman_ii(OUT, LD, I"Index.Elements.Fi.ThumbnailLimit",
MAX_INDEXED_FIGURES, 10*MAX_INDEXED_FIGURES);
WRITE(")");
HTML_CLOSE("p");
}
@<Find image format and dimensions@> =
FILE *FIGURE_FILE = Filenames::fopen(F, "rb");
if (FIGURE_FILE) {
text_stream *real_format = I"JPEG";
format_found = ImageFiles::get_JPEG_dimensions(FIGURE_FILE, &width, &height);
fclose(FIGURE_FILE);
if (format_found == 0) {
FIGURE_FILE = Filenames::fopen(F, "rb");
if (FIGURE_FILE) {
real_format = I"PNG";
format_found = ImageFiles::get_PNG_dimensions(FIGURE_FILE, &width, &height);
fclose(FIGURE_FILE);
}
}
if (format_found == 0) {
Localisation::italic(description, LD, I"Index.Elements.Fi.UnknownFormat");
} else {
Localisation::roman_t(description, LD, I"Index.Elements.Fi.Format", real_format);
WRITE_TO(description, ": ");
Localisation::roman_ii(description, LD, I"Index.Elements.Fi.Dimensions",
(int) width, (int) height);
}
} else {
Localisation::italic(description, LD, I"Index.Elements.Fi.Missing");
}
@<Render a table row for the image@> =
HTML::first_html_column(OUT, THUMBNAIL_WIDTH+10);
if (format_found == 0) {
HTML_TAG_WITH("img",
"border=\"0\" src=\"inform:/doc_images/image_problem.png\"");
WRITE("&nbsp;");
} else if (count_of_displayed_figures++ < MAX_INDEXED_FIGURES) {
HTML_TAG_WITH("img",
"border=\"1\" src=\"file://%f\" width=\"%d\" height=\"%d\"",
F, THUMBNAIL_WIDTH, THUMBNAIL_WIDTH*height/width);
WRITE("&nbsp;");
} else {
HTML_OPEN_WITH("div",
"class=\"figureindexbox\" style=\"width:%dpx; height:%dpx; border:1px solid;\"",
THUMBNAIL_WIDTH, THUMBNAIL_WIDTH*height/width);
WRITE("&nbsp;");
HTML_CLOSE("div");
}
HTML::next_html_column(OUT, 0);
WRITE("%S", Metadata::required_textual(pack, I"^name"));
IndexUtilities::link_package(OUT, pack);
HTML_TAG("br");
if (Str::len(description) > 0) {
WRITE("%S", description);
HTML_TAG("br");
}
Localisation::roman_ti(description, LD, I"Index.Elements.Fi.Resource",
Filenames::get_leafname(F), (int) id);
HTML::end_html_row(OUT);
@h Sounds.
@<Index the sounds@> =
HTML_OPEN("p");
Localisation::bold(OUT, LD, I"Index.Elements.Fi.ListOfSounds");
HTML_CLOSE("p");
if (InterNodeList::array_len(inv->sound_nodes) == 0) {
HTML_OPEN("p");
Localisation::roman(OUT, LD, I"Index.Elements.Fi.NoSounds");
HTML_CLOSE("p");
} else {
@<Tabulate the sounds@>;
}
@<Tabulate the sounds@> =
HTML::begin_html_table(OUT, NULL, TRUE, 0, 0, 0, 0, 0);
inter_package *pack;
LOOP_OVER_INVENTORY_PACKAGES(pack, i, inv->sound_nodes) {
inter_ti id = Metadata::read_numeric(pack, I"^resource_id");
text_stream *filename_as_text = Metadata::required_textual(pack, I"^filename");
filename *F = Filenames::from_text(filename_as_text);
unsigned int duration, pBitsPerSecond, pChannels, pSampleRate, fsize,
midi_version = 0, no_tracks = 0;
int preview = TRUE, waveform_style = TRUE;
TEMPORARY_TEXT(description)
int format_found = 0;
@<Find sound format and duration@>
@<Render a table row for the sound@>;
DISCARD_TEXT(description)
}
HTML::end_html_table(OUT);
@<Find sound format and duration@> =
FILE *SOUND_FILE = Filenames::fopen(F, "rb");
if (SOUND_FILE) {
text_stream *real_format = I"AIFF";
format_found = SoundFiles::get_AIFF_duration(SOUND_FILE, &duration, &pBitsPerSecond,
&pChannels, &pSampleRate);
fseek(SOUND_FILE, 0, SEEK_END);
fsize = (unsigned int) (ftell(SOUND_FILE));
fclose(SOUND_FILE);
if (format_found == 0) {
SOUND_FILE = Filenames::fopen(F, "rb");
if (SOUND_FILE) {
real_format = I"Ogg Vorbis";
preview = FALSE;
format_found = SoundFiles::get_OggVorbis_duration(SOUND_FILE, &duration,
&pBitsPerSecond, &pChannels, &pSampleRate);
fclose(SOUND_FILE);
}
}
if (format_found == 0) {
SOUND_FILE = Filenames::fopen(F, "rb");
if (SOUND_FILE) {
waveform_style = FALSE;
real_format = I"MIDI";
preview = TRUE;
format_found = SoundFiles::get_MIDI_information(SOUND_FILE,
&midi_version, &no_tracks);
fclose(SOUND_FILE);
}
}
if (format_found == 0) {
Localisation::italic(description, LD, I"Index.Elements.Fi.UnknownSoundFormat");
} else {
if (waveform_style == FALSE) @<Describe sound in MIDI format@>
else @<Describe sound in waveform format@>;
}
} else {
Localisation::italic(description, LD, I"Index.Elements.Fi.MissingSound");
}
@<Describe sound in MIDI format@> =
if (no_tracks == 1) {
Localisation::roman_it(description, LD, I"Index.Elements.Fi.SoundFormatOneTrack",
(int) midi_version, real_format);
} else {
Localisation::write_iti(description, LD, I"Index.Elements.Fi.SoundFormatMultiTrack",
(int) midi_version, real_format, (int) no_tracks);
}
WRITE_TO(description, " - ");
Localisation::italic(description, LD, I"Index.Elements.Fi.SoundUnsupported");
@<Describe sound in waveform format@> =
TEMPORARY_TEXT(size)
WRITE_TO(size, "%d.%01dKB", fsize/1024, (fsize%1024)/102);
Localisation::roman_tt(description, LD, I"Index.Elements.Fi.SoundFile", size, real_format);
DISCARD_TEXT(size)
int min = (duration/6000), sec = (duration%6000)/100, centisec = (duration%100);
WRITE_TO(description, ": ");
TEMPORARY_TEXT(seconds)
if (centisec == 0) WRITE_TO(seconds, "%d", sec);
else WRITE_TO(seconds, "%d.%02d", sec, centisec);
if (min > 0) {
if ((sec > 0) || (centisec > 0)) {
Localisation::roman_it(description, LD, I"Index.Elements.Fi.DurationMS",
min, seconds);
} else {
Localisation::roman_i(description, LD, I"Index.Elements.Fi.DurationM", min);
}
} else {
Localisation::roman_t(description, LD, I"Index.Elements.Fi.DurationS", seconds);
}
DISCARD_TEXT(seconds)
WRITE_TO(description, "<br>");
TEMPORARY_TEXT(sample)
WRITE_TO(sample, "%d.%01dkHz", pSampleRate/1000, (pSampleRate%1000)/100);
Localisation::roman_t(description, LD, I"Index.Elements.Fi.Sampled", sample);
DISCARD_TEXT(sample)
WRITE_TO(description, " ");
if (pChannels == 1) Localisation::roman(OUT, LD, I"Index.Elements.Fi.Mono");
else Localisation::roman(description, LD, I"Index.Elements.Fi.Stereo");
WRITE_TO(description, " (");
TEMPORARY_TEXT(bitrate)
WRITE_TO(bitrate, "%d.%01d", pBitsPerSecond/1000, (pSampleRate%1000)/100);
Localisation::roman_t(description, LD, I"Index.Elements.Fi.BitRate", bitrate);
DISCARD_TEXT(bitrate)
WRITE_TO(description, ")");
@<Render a table row for the sound@> =
HTML::first_html_column(OUT, THUMBNAIL_WIDTH+10);
if (format_found == 0) {
HTML_TAG_WITH("img", "border=\"0\" src=\"inform:/doc_images/image_problem.png\"");
} else if (preview) {
HTML_OPEN_WITH("embed",
"src=\"file://%f\" width=\"%d\" height=\"64\" "
"autostart=\"false\" volume=\"50%%\" mastersound",
F, THUMBNAIL_WIDTH);
HTML_CLOSE("embed");
} else {
HTML_TAG_WITH("img", "border=\"0\" src=\"inform:/doc_images/sound_okay.png\"");
}
WRITE("&nbsp;");
HTML::next_html_column(OUT, 0);
WRITE("%S", Metadata::required_textual(pack, I"^name"));
IndexUtilities::link_package(OUT, pack);
HTML_TAG("br");
if (Str::len(description) > 0) {
WRITE("%S", description);
HTML_TAG("br");
}
Localisation::roman_ti(description, LD, I"Index.Elements.Fi.Resource",
Filenames::get_leafname(F), (int) id);
HTML::end_html_row(OUT);
@h Internal files.
@d EXTERNAL_TEXT_FILE_NFSMF 0
@d EXTERNAL_BINARY_FILE_NFSMF 1
@d INTERNAL_TEXT_FILE_NFSMF 2
@d INTERNAL_BINARY_FILE_NFSMF 3
@<Index the internal files@> =
HTML_OPEN("p");
Localisation::bold(OUT, LD, I"Index.Elements.Fi.ListOfInternalFiles");
HTML_CLOSE("p");
if (InterNodeList::array_len(inv->internal_file_nodes) == 0) {
HTML_OPEN("p");
Localisation::roman(OUT, LD, I"Index.Elements.Fi.NoInternalFiles");
HTML_CLOSE("p");
} else {
@<Tabulate the internal files@>;
}
@<Tabulate the internal files@> =
HTML::begin_html_table(OUT, NULL, TRUE, 0, 0, 0, 0, 0);
inter_package *pack;
LOOP_OVER_INVENTORY_PACKAGES(pack, i, inv->internal_file_nodes) {
inter_ti id = Metadata::read_numeric(pack, I"^resource_id");
text_stream *filename_as_text = Metadata::required_textual(pack, I"^filename");
filename *F = Filenames::from_text(filename_as_text);
inter_ti format = Metadata::read_numeric(pack, I"^internal_file_format");
TEMPORARY_TEXT(description)
TEMPORARY_TEXT(preview)
@<Find internal file preview@>;
@<Render a table row for the internal file@>;
DISCARD_TEXT(description)
DISCARD_TEXT(preview)
}
HTML::end_html_table(OUT);
@<Find internal file preview@> =
FILE *INTERNAL_FILE = Filenames::fopen(F, "rb");
if (INTERNAL_FILE) {
switch (format) {
case INTERNAL_TEXT_FILE_NFSMF:
WRITE_TO(description, "%S", filename_as_text);
@<Offer a textual preview@>;
break;
case INTERNAL_BINARY_FILE_NFSMF:
WRITE_TO(description, "%S", filename_as_text);
@<Offer a binary preview@>;
break;
}
} else {
Localisation::italic(description, LD, I"Index.Elements.Fi.MissingInternalFile");
}
@<Offer a textual preview@> =
for (int row = 0; row < 6; ) {
int col = 0;
unsigned int B, line_ended = FALSE;
while (BinaryFiles::read_int8(INTERNAL_FILE, &B)) {
if ((B == 10) || (B == 13)) { line_ended = TRUE; break; }
if (col++ >= 80) { WRITE_TO(preview, "[...]"); line_ended = TRUE; break; }
if ((B >= 0x20) && (B <= 0x7E)) WRITE_TO(preview, "%c", B);
else WRITE_TO(preview, "?");
}
if (line_ended == FALSE) break;
if (col > 0) row++;
WRITE_TO(preview, "\n");
}
@<Offer a binary preview@> =
for (int row = 0; row < 6; row++) {
unsigned int bytes[16];
for (int col = 0; col < 16; col++) {
if (!BinaryFiles::read_int8(INTERNAL_FILE, &(bytes[col]))) {
for (; col < 16; col++) bytes[col] = 256;
row = 6; break;
}
}
for (int col = 0; col < 16; col++) {
if (bytes[col] < 256) WRITE_TO(preview, "%02x ", bytes[col]);
else WRITE_TO(preview, ".. ");
}
for (int col = 0; col < 16; col++) {
if ((bytes[col] >= 0x20) && (bytes[col] <= 0x7E)) WRITE_TO(preview, "%c", bytes[col]);
else WRITE_TO(preview, ".");
}
WRITE_TO(preview, "\n");
}
@<Render a table row for the internal file@> =
HTML::first_html_column(OUT, THUMBNAIL_WIDTH+10);
if (Str::len(description) == 0) {
HTML_TAG_WITH("img", "border=\"0\" src=\"inform:/doc_images/image_problem.png\"");
} else {
HTML_TAG_WITH("img", "border=\"0\" src=\"inform:/doc_images/data.png\"");
}
WRITE("&nbsp;");
HTML::next_html_column(OUT, 0);
HTML_OPEN_WITH("p", "class=\"hang\"");
switch (format) {
case INTERNAL_TEXT_FILE_NFSMF: WRITE("(text) "); break;
case INTERNAL_BINARY_FILE_NFSMF: WRITE("(binary) "); break;
}
WRITE("%S", Metadata::required_textual(pack, I"^name"));
IndexUtilities::link_package(OUT, pack);
if (Str::len(description) > 0) {
HTML_TAG("br");
WRITE("%S", description);
}
HTML_CLOSE("p");
if (Str::len(preview) > 0) {
HTML_OPEN("pre");
int N = Streams::get_indentation(OUT);
Streams::set_indentation(OUT, 0);
WRITE("\n%S", preview);
Streams::set_indentation(OUT, N);
HTML_CLOSE("pre");
WRITE("\n");
}
HTML_OPEN("p");
Localisation::roman_ti(description, LD, I"Index.Elements.Fi.Resource",
Filenames::get_leafname(F), (int) id);
HTML_CLOSE("p");
HTML::end_html_row(OUT);
@h Files.
This is more or less perfunctory, but still of some use, if only as a list.
@<Index the files@> =
HTML_OPEN("p");
Localisation::bold(OUT, LD, I"Index.Elements.Fi.ListOfFiles");
HTML_CLOSE("p");
if (InterNodeList::array_len(inv->file_nodes) == 0) {
HTML_OPEN("p");
Localisation::roman(OUT, LD, I"Index.Elements.Fi.NoFiles");
HTML_CLOSE("p");
} else {
@<Tabulate the files@>;
}
@<Tabulate the files@> =
HTML::begin_html_table(OUT, NULL, TRUE, 0, 0, 0, 0, 0);
inter_package *pack;
LOOP_OVER_INVENTORY_PACKAGES(pack, i, inv->file_nodes) {
HTML::first_html_column(OUT, THUMBNAIL_WIDTH+10);
int is_binary = (int) Metadata::read_optional_numeric(pack, I"^is_binary");
if (is_binary) {
HTML_TAG_WITH("img", "border=\"0\" src=\"inform:/doc_images/exf_binary.png\"");
} else {
HTML_TAG_WITH("img", "border=\"0\" src=\"inform:/doc_images/exf_text.png\"");
}
WRITE("&nbsp;");
HTML::next_html_column(OUT, 0);
WRITE("%S", Metadata::required_textual(pack, I"^name"));
IndexUtilities::link_package(OUT, pack);
HTML_TAG("br");
if (is_binary)
Localisation::roman_t(OUT, LD, I"Index.Elements.Fi.BinaryFile",
Metadata::required_textual(pack, I"^leafname"));
else
Localisation::roman_t(OUT, LD, I"Index.Elements.Fi.TextFile",
Metadata::required_textual(pack, I"^leafname"));
WRITE(" - ");
if (Metadata::read_optional_numeric(pack, I"^file_owned")) {
Localisation::roman(OUT, LD, I"Index.Elements.Fi.FileOwnedByThis");
} else if (Metadata::read_optional_numeric(pack, I"^file_owned_by_other")) {
Localisation::roman(OUT, LD, I"Index.Elements.Fi.FileOwnedByOther");
} else {
Localisation::roman_t(OUT, LD, I"Index.Elements.Fi.FileOwnedBy",
Metadata::required_textual(pack, I"^file_owner"));
}
HTML::end_html_row(OUT);
}
HTML::end_html_table(OUT);