To manage the line skips which space paragraphs out, and to handle the printing of names of objects, pieces of text and numbers.


§1. Prompt. This is the text printed just before we wait for the player's command: it prompts him to type.

[ PrintPrompt i;
    RunTimeProblemShow();
    ClearRTP();
    style roman;
    EnsureBreakBeforePrompt();
    TEXT_TY_Say(CommandPromptText());
    ClearBoxedText();
    ClearParagraphing(14);
];

§2. Boxed Quotations. These appear once only, and happen outside of the paragraphing scheme: they are normally overlaid as windows on top of the regular text. We can request one at any time, but it will appear only at prompt time, when the screen is fairly well guaranteed not to be scrolling. (Only fairly well since it's just possible that {\it Border Zone}-like tricks with real-time play might be going on, but whatever happens, there is at least a human-appreciable pause in which the quotation can be read before being taken away again.)

Global pending_boxed_quotation; a routine to overlay the quotation on screen

[ DisplayBoxedQuotation Q;
    pending_boxed_quotation = Q;
];

[ ClearBoxedText i;
    if (pending_boxed_quotation) {
        ClearParagraphing(15);
        pending_boxed_quotation();
        ClearParagraphing(16);
        pending_boxed_quotation = 0;
    }
];

§3. Score Notification. This doesn't really deserve to be at I6 level at all, but since we want a fancy text style for Glulx, ...

[ NotifyTheScore d;
    if ((KIT_CONFIGURATION_BITMAP & USE_SCORING_TCBIT) && (notify_mode == 1)) {
        DivideParagraphPoint();
        VM_Style(NOTE_VMSTY);
        d = score-last_score;
        if (d > 0) { ANNOUNCE_SCORE_RM('D', d); }
        else if (d < 0) { ANNOUNCE_SCORE_RM('E', -d); }
        new_line;
        VM_Style(NORMAL_VMSTY);
    }
];

§4. Print Rank. The table of scoring ranks is a residue from the ancient times of early IF: it gets a tiny amount of special treatment here, even though I7 works tend not to use these now dated conventions.

[ PrintRank i j v;
    if (KIT_CONFIGURATION_BITMAP & RANKING_TABLE_TCBIT) {
        ANNOUNCE_SCORE_RM('B');
        j = TableRows(RANKING_TABLE);
        for (i=j:i>=1:i--)
            if (score >= TableLookUpEntry(RANKING_TABLE, 1, i)) {
                v = TableLookUpEntry(RANKING_TABLE, 2, i);
                TEXT_TY_Say(v);
                ".";
            }
    }
    ".";
];

§5. Status Line. Status line printing happens on the upper screen window, and outside of the paragraph control system.

Support for version 6 of the Z-machine is best described as grudging. It requires a heavily rewritten DrawStatusLine equivalent, to be found in "ZMachine.i6t".

[ DrawStatusLine width posb;
    @push say__p; @push say__pc;
    BeginActivity(CONSTRUCTING_STATUS_LINE_ACT);
    VM_StatusLineHeight(1); VM_MoveCursorInStatusLine(1, 1);
    if (statuswin_current) {
        width = VM_ScreenWidth(); posb = width-15;
        spaces width;
        ClearParagraphing(17);
        if (ForActivity(CONSTRUCTING_STATUS_LINE_ACT) == false) {
            VM_MoveCursorInStatusLine(1, 2);
            TEXT_TY_Say(left_hand_status_line);
            VM_MoveCursorInStatusLine(1, posb);
            TEXT_TY_Say(right_hand_status_line);
        }
        VM_MoveCursorInStatusLine(1, 1); VM_MainWindow();
    }
    ClearParagraphing(18);
    EndActivity(CONSTRUCTING_STATUS_LINE_ACT);
    @pull say__pc; @pull say__p;
];

§6. Status Line Utilities. Two convenient routines for the default values of right_hand_status_line and left_hand_status_line respectively. SL_Location also implements the text substitution "[player's surroundings]".

Array T_SL_Score_Moves --> CONSTANT_PACKED_TEXT_STORAGE SL_Score_Moves;

[ SL_Score_Moves;
    if (not_yet_in_play) return;
    if (KIT_CONFIGURATION_BITMAP & USE_SCORING_TCBIT)
        print sline1, "/", sline2;
];

Array T_SL_Location --> CONSTANT_PACKED_TEXT_STORAGE SL_Location;

[ SL_Location even_before;
    if ((not_yet_in_play) && (even_before == false)) return;
    if (location == thedark) {
        BeginActivity(PRINTING_NAME_OF_DARK_ROOM_ACT);
        if (ForActivity(PRINTING_NAME_OF_DARK_ROOM_ACT) == false)
            DARKNESS_NAME_INTERNAL_RM('A');
        EndActivity(PRINTING_NAME_OF_DARK_ROOM_ACT);
    } else {
        FindVisibilityLevels();
        if (visibility_ceiling == location) print (name) location;
        else print (The) visibility_ceiling;
    }
];

[ DARKNESS_NAME_INTERNAL_R; ];

§7. Banner. Note that Inform always compiles Story and Headline texts, but does not always compile a Story_Author.

[ Banner;
   BeginActivity(PRINTING_BANNER_TEXT_ACT);
   if (ForActivity(PRINTING_BANNER_TEXT_ACT) == false) {
        VM_Style(HEADER_VMSTY);
        TEXT_TY_Say(Story);
        VM_Style(NORMAL_VMSTY);
        new_line;
        TEXT_TY_Say(Headline);
        if (KIT_CONFIGURATION_BITMAP & STORY_AUTHOR_TCBIT) {
            print " by "; TEXT_TY_Say(Story_Author);
        }
        new_line;
        VM_Describe_Release();
        print " / Inform 7 v", (PrintI6Text) I7_VERSION_NUMBER;
        #Ifdef DEBUG;
        print " / D";
        #Endif; DEBUG
        new_line;
    }
    EndActivity(PRINTING_BANNER_TEXT_ACT);
];

§8. Short Name Storage. None of the following functions should be called for the Z-machine if the short name exceeds the size of the following buffer: whereas the Glulx implementation of VM_PrintToBuffer will safely truncate overlong text, that's impossible for the Z-machine, and horrible results will follow.

CPrintOrRun is a variation on PrintOrRun, simplified by not needing to handle entire paragraphs (so, no fuss about dividing) but complicated by having to capitalise the first letter. We do this by writing to the buffer and then altering the first character.

Array StorageForShortName buffer 250;

[ CPrintOrRun obj prop  v length i;
    if ((obj ofclass String or Routine) || (prop == 0))
        VM_PrintToBuffer (StorageForShortName, 160, obj);
    else {
        if (obj.prop == NULL) rfalse;
        if (metaclass(obj.prop) == Routine or String)
            VM_PrintToBuffer(StorageForShortName, 160, obj, prop);
        else return RunTimeError(2, obj, prop);
    }

    length = StorageForShortName-->0;

    StorageForShortName->WORDSIZE = VM_LowerToUpperCase(StorageForShortName->WORDSIZE);
    for (i=WORDSIZE: i<length+WORDSIZE: i++) print (char) StorageForShortName->i;
    if (i>WORDSIZE) say__p = 1;

    return;
];

[ Cap str nocaps;
    if (nocaps) print (string) str;
    else CPrintOrRun(str, 0);
];

§9. Object Names I. We now begin the work of printing object names. In the lowest level of this process we print just the name itself (without articles attached), and we do it by carrying out an activity.

[ PSN__ o;
    if (o == 0) { LIST_WRITER_INTERNAL_RM('Y'); rtrue; }
    switch (metaclass(o)) {
        Routine:  print "<routine ", o, ">"; rtrue;
        String:   print "<string ~", (string) o, "~>"; rtrue;
        nothing:  print "<illegal object number ", o, ">"; rtrue;
    }
    RegardingSingleObject(o);
    CarryOutActivity(PRINTING_THE_NAME_ACT, o);
];

[ PrintShortName obj i;
    i = indef_mode; indef_mode = NULL;
    PSN__(obj); indef_mode = i;
];

§10. Standard Name Printing Rule. In its initial state, the "printing the name of" activity has just one rule: the following "for" rule.

Global caps_mode = false;

[ STANDARD_NAME_PRINTING_R obj;
    obj = parameter_value;
    if (obj == 0) {
        LIST_WRITER_INTERNAL_RM('Y'); return;
    }
    switch (metaclass(obj)) {
        Routine:  print "<routine ", obj, ">"; return;
        String:   print "<string ~", (string) obj, "~>"; return;
        nothing:  print "<illegal object number ", obj, ">"; return;
    }
    if (obj == player) {
        if (indef_mode == NULL && caps_mode) PRINT_PROTAGONIST_INTERNAL_RM('A');
        else PRINT_PROTAGONIST_INTERNAL_RM('B');
        return;
    }
    #Ifdef LanguagePrintShortName;
    if (LanguagePrintShortName(obj)) return;
    #Endif; LanguagePrintShortName
    if (indef_mode && obj provides short_name_indef &&
        PrintOrRun(obj, short_name_indef, true) ~= 0) return;
    if (caps_mode &&
        obj provides cap_short_name && PrintOrRun(obj, cap_short_name, true) ~= 0) {
        caps_mode = false;
        return;
    }
    if (obj provides short_name && PrintOrRun(obj, short_name, true) ~= 0) return;
    print (object) obj;
];

[ STANDARD_PLURAL_NAME_PRINTING_R obj;
    obj = parameter_value;
    PrintOrRun(obj, plural, true);
];

§11. Internal Rule.

[ PRINT_PROTAGONIST_INTERNAL_R; ];

§12. Object Names II. The second level of the system for printing object names handles the placing of articles in front of them: {\it the} red herring, {\it an} elephant, {\it Some} bread. The following routine allows us to choose:

The routine then looks after issues such as which contraction form to use: for instance, in English, whether to use "a" or "an" for the indefinite singular depends on the text of the object's name.

Global short_name_case;

[ PrefaceByArticle obj acode pluralise capitalise  i artform findout artval;
    if (obj provides articles) {
        artval=(obj.&articles)-->(acode+short_name_case*LanguageCases);
        if (capitalise)
            print (Cap) artval;
        else
            print (string) artval;
        if (pluralise) return;
        print (PSN__) obj; return;
    }

    i = GetGNAOfObject(obj);
    if (pluralise) {
        if (i < 3 || (i >= 6 && i < 9)) i = i + 3;
    }
    i = LanguageGNAsToArticles-->i;

    artform = LanguageArticles
        + 3*WORDSIZE*LanguageContractionForms*(short_name_case + i*LanguageCases);

    switch (LanguageContractionForms) {
        2: if (artform-->acode ~= artform-->(acode+3)) findout = true;
        3: if (artform-->acode ~= artform-->(acode+3)) findout = true;
           if (artform-->(acode+3) ~= artform-->(acode+6)) findout = true;
        4: if (artform-->acode ~= artform-->(acode+3)) findout = true;
           if (artform-->(acode+3) ~= artform-->(acode+6)) findout = true;
           if (artform-->(acode+6) ~= artform-->(acode+9)) findout = true;
        default: findout = true;
    }
    #Ifdef TARGET_ZCODE;
    if (standard_interpreter ~= 0 && findout) {
        StorageForShortName-->0 = 160;
        @output_stream 3 StorageForShortName;
        if (pluralise) print (number) pluralise; else print (PSN__) obj;
        @output_stream -3;
        acode = acode + 3*LanguageContraction(StorageForShortName + 2);
    }
    #Ifnot; TARGET_GLULX
    if (findout) {
        if (pluralise)
            Glulx_PrintAnyToArray(StorageForShortName, 160, EnglishNumber, pluralise);
        else
            Glulx_PrintAnyToArray(StorageForShortName, 160, PSN__, obj);
        acode = acode + 3*LanguageContraction(StorageForShortName);
    }
    #Endif; TARGET_

    Cap (artform-->acode, ~~capitalise); print article
    if (pluralise) return;
    print (PSN__) obj;
];

§13. Object Names III. The routines accessible from outside this segment.

[ IndefArt obj i s;
    if (obj == 0) { LIST_WRITER_INTERNAL_RM('Y'); rtrue; }
    i = indef_mode; indef_mode = true; s = self; self = obj;
    if (obj has proper) { indef_mode = NULL; print (PSN__) obj; indef_mode = i; self = s; return; }
    if ((obj provides article) && (TEXT_TY_Compare(obj.article, EMPTY_TEXT_VALUE) ~= 0)) {
        PrintOrRun(obj, article, true); print " ", (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 2); indef_mode = i; self = s;
];

[ CIndefArt obj i s;
    if (obj == 0) { LIST_WRITER_INTERNAL_RM('X'); rtrue; }
    i = indef_mode; indef_mode = true; s = self; self = obj;
    if (obj has proper) {
        indef_mode = NULL;
        caps_mode = true;
        print (PSN__) obj;
        indef_mode = i;
        caps_mode = false;
        self = s;
        return;
    }
    if ((obj provides article) && (TEXT_TY_Compare(obj.article, EMPTY_TEXT_VALUE) ~= 0)) {
        TEXT_TY_Say_Capitalised(obj.article); print " ", (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 2, 0, 1); indef_mode = i; self = s;
];

[ DefArt obj i s;
    i = indef_mode; indef_mode = false; s = self; self = obj;
    if ((~~obj ofclass Object) || obj has proper) {
        indef_mode = NULL; print (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 1); indef_mode = i; self = s;
];

[ CDefArt obj i s;
    i = indef_mode; indef_mode = false; s = self; self = obj;
    if ((obj ofclass Object) && (obj has proper || obj == player)) {
        indef_mode = NULL;
        caps_mode = true;
        print (PSN__) obj;
        indef_mode = i;
        caps_mode = false;
        self = s;
        return;
    }
    if ((~~obj ofclass Object) || obj has proper) {
        indef_mode = NULL; print (PSN__) obj; indef_mode = i; self = s;
        return;
    }
    PrefaceByArticle(obj, 0); indef_mode = i; self = s;
];

§14. Standard Response Issuing Rule. To print a response, we trigger off the response issuing activity. The following is the default "for" rule for that activity:

[ STANDARD_RESPONSE_ISSUING_R;
    RegardingSingleObject();
    TEXT_TY_Say(ResponseTexts-->(parameter_value - 1));
];