[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); @; @; @; @; } @h 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"); @; } @ 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 = @ = 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; @; @; 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"); } @ = 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"); } @ = 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(" "); } 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(" "); } else { HTML_OPEN_WITH("div", "class=\"figureindexbox\" style=\"width:%dpx; height:%dpx; border:1px solid;\"", THUMBNAIL_WIDTH, THUMBNAIL_WIDTH*height/width); WRITE(" "); 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. @ = 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 { @; } @ = 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; @ @; DISCARD_TEXT(description) } HTML::end_html_table(OUT); @ = 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) @ else @; } } else { Localisation::italic(description, LD, I"Index.Elements.Fi.MissingSound"); } @ = 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"); @ = 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, "
"); TEMPORARY_TEXT(sample) WRITE_TO(sample, "%d.%01dkHz", pSampleRate/1000, (pSampleRate%1000)/100); Localisation::roman_t(OUT, 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(OUT, 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(OUT, LD, I"Index.Elements.Fi.BitRate", bitrate); DISCARD_TEXT(bitrate) WRITE_TO(description, ")"); @ = 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(" "); 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 @d INTERNAL_FORM_FILE_NFSMF 4 @ = 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 { @; } @ = 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) @; @; DISCARD_TEXT(description) DISCARD_TEXT(preview) } HTML::end_html_table(OUT); @ = FILE *INTERNAL_FILE = Filenames::fopen(F, "rb"); if (INTERNAL_FILE) { switch (format) { case INTERNAL_TEXT_FILE_NFSMF: WRITE_TO(description, "%S", filename_as_text); @; break; case INTERNAL_BINARY_FILE_NFSMF: WRITE_TO(description, "%S", filename_as_text); @; break; case INTERNAL_FORM_FILE_NFSMF: WRITE_TO(description, "%S", filename_as_text); @; break; } } else { Localisation::italic(description, LD, I"Index.Elements.Fi.MissingInternalFile"); } @ = 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"); } @ = 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"); } @ = 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(" "); 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; case INTERNAL_FORM_FILE_NFSMF: WRITE("(form) "); 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. @ = 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 { @; } @ = 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(" "); 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);