To manage links to auxiliary files, and placeholder variables.


§1. Auxiliary files are for items bundled up with the release but which are deliberately made accessible for the eventual player: things such as maps or manuals. Inblorb needs to know about these only when releasing a website; they are also recorded in an iFiction record, but Inblorb does not create that (ni does).

    typedef struct auxiliary_file {
        struct filename *full_filename;
        struct text_stream *aux_leafname;
        struct text_stream *aux_subfolder;
        struct text_stream *description;
        struct text_stream *format; e.g., "jpg", "pdf"
        MEMORY_MANAGEMENT
    } auxiliary_file;

The structure auxiliary_file is accessed in 2/bw and here.

§2. Registration. The format text is set to a lower-case version of the filename extension, and the URL to the filename itself; except when there is no extension, so that the auxiliary resource is a mini-website in a subfolder of the release website. In that case the format is link and the URL is to the index file in the subfolder.

    void Links::create_auxiliary_file(text_stream *fn, text_stream *description, text_stream *subfolder) {
        auxiliary_file *aux = CREATE(auxiliary_file);
        aux->description = Str::duplicate(description);
        aux->aux_subfolder = Str::duplicate(subfolder);
        TEMPORARY_TEXT(ext);
        Links::get_extension_from_textual_filename(ext, fn);
        TEMPORARY_TEXT(leaf);
        Links::get_leafname_from_textual_filename(leaf, fn);
        if (Str::get_first_char(ext) == '.') {
            aux->full_filename = Filenames::from_text(fn);
            aux->format = Str::duplicate(ext);
            Str::delete_first_character(aux->format);
            LOOP_THROUGH_TEXT(pos, aux->format)
                Str::put(pos, Characters::tolower(Str::get(pos)));
        } else {
            aux->full_filename = NULL;
            aux->format = I"link";
        }
        aux->aux_leafname = Str::duplicate(leaf);
        DISCARD_TEXT(ext);
        DISCARD_TEXT(leaf);

        PRINT("! Auxiliary file: <%S> = <%S>\n", fn, description);
    }

    void Links::get_extension_from_textual_filename(OUTPUT_STREAM, text_stream *filename) {
        int i = Str::len(filename) - 1;
        while ((i>=0) && ((Str::get_at(filename, i) == '.') || (Str::get_at(filename, i) == ' '))) i--;
        while ((i>=0) && (Str::get_at(filename, i) != '.') && (Str::get_at(filename, i) != FOLDER_SEPARATOR)) i--;
        if ((i<0) || (Str::get_at(filename, i) == FOLDER_SEPARATOR)) return;
        Str::copy_tail(OUT, filename, i);
    }

The function Links::create_auxiliary_file is used in 1/bp (§7.2).

The function Links::get_extension_from_textual_filename appears nowhere else.

§3.

    void Links::get_leafname_from_textual_filename(OUTPUT_STREAM, text_stream *filename) {
        int i = Str::len(filename) - 1;
        while ((i>=0) && (Str::get_at(filename, i) != FOLDER_SEPARATOR)) i--;
        Str::copy_tail(OUT, filename, i+1);
    }

The function Links::get_leafname_from_textual_filename is used in §2.

§4. Linking. The list of links to auxiliary resources is written using <li>...</li> list entry tags, for convenience of CSS styling.

    void Links::expand_AUXILIARY_variable(OUTPUT_STREAM) {
        auxiliary_file *aux;
        LOOP_OVER(aux, auxiliary_file) {
            if (Str::eq_wide_string(aux->description, L"--") == FALSE) {
                WRITE("<li>");
                Links::download_link(OUT,
                    aux->description, aux->full_filename, aux->aux_leafname, aux->format);
                WRITE("</li>");
            }
        }
        Requests::add_links_to_requested_resources(OUT);
    }

The function Links::expand_AUXILIARY_variable is used in 3/plc (§7).

§5. On some of the pages produced by Inblorb the story file itself looks like another auxiliary resource, but it's produced thus:

    void Links::expand_DOWNLOAD_variable(OUTPUT_STREAM) {
        filename *eventual_Blorb_location =
            Filenames::in_folder(release_folder, Placeholders::read(I"STORYFILE"));
        Links::download_link(OUT, I"Story File", eventual_Blorb_location,
            Placeholders::read(I"STORYFILE"), I"Blorb");
    }

The function Links::expand_DOWNLOAD_variable is used in 3/plc (§7).

§6. Links. This routine, then, handles either kind of link.

    void Links::download_link(OUTPUT_STREAM, text_stream *desc, filename *F, text_stream *relative_url, text_stream *form) {
        int size_up = TRUE;
        if (Str::eq_wide_string(form, L"link")) size_up = FALSE;
        WRITE("<a href=\"%S\">%S</a> ", relative_url, desc);
        Websites::open_style(OUT, "filetype");
        WRITE("(%S", form);
        if (size_up) {
            long int size = -1L;
            if (Str::eq_wide_string(desc, L"Story File")) size = (long int) blorb_file_size;
            else size = BinaryFiles::size(F);
            if (size != -1L) <Write a description of the rough file size 6.1>
        }
        WRITE(")");
        Websites::close_style(OUT, "filetype");
    }

The function Links::download_link is used in §4, §5, 3/rls (§10).

§6.1. We round down to the nearest KB, MB, GB, TB or byte, as appropriate. Although this will describe a 1-byte auxiliary file as "1 bytes", the contingency seems remote.

<Write a description of the rough file size 6.1> =

        text_stream *units = I"&nbsp;bytes";
        long int remainder = 0;
        if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = I"KB"; }
        if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = I"MB"; }
        if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = I"GB"; }
        if (size > 1024L) { remainder = size % 1024L; size /= 1024L; units = I"TB"; }
        WRITE(",&nbsp;%d", (int) size);
        if ((size < 100L) && (remainder >= 103L)) WRITE(".%d", (int) (remainder/103L));
        WRITE("%S", units);

This code is used in §6.

§7. Cover image. Note that if the large cover image is a PNG, so is the small (thumbnail) version, and vice versa — supplying "Cover.jpg" and "Small Cover.png" will not work.

    void Links::expand_COVER_variable(OUTPUT_STREAM) {
        if (cover_exists) {
            char *format = "png"; if (cover_is_in_JPEG_format) format = "jpg";
            WRITE("<a href=\"Cover.%s\"><img src=\"Small Cover.%s\" border=\"1\"></a>",
                format, format);
        }
    }

The function Links::expand_COVER_variable is used in 3/plc (§7).

§8. Releasing. When we generate a website, we need to copy the auxiliary files into it (though not mini-websites: the user will have to do that).

    void Links::request_copy_of_auxiliaries(void) {
        auxiliary_file *aux;
        LOOP_OVER(aux, auxiliary_file)
            if (Str::eq(aux->format, I"link")) {
                if (verbose_mode)
                    PRINT("! COPY <%f> as <%S>\n", aux->full_filename, aux->aux_leafname);
                TEMPORARY_TEXT(as_text);
                WRITE_TO(as_text, "%f", aux->full_filename);
                Requests::request_copy(as_text, aux->aux_leafname, aux->aux_subfolder);
                DISCARD_TEXT(as_text);
            }
    }

The function Links::request_copy_of_auxiliaries is used in 3/rls (§5).