Undo Output Control

version 3/110717 by Erik Temple

  • Home page
  • Beginning
  • Previous
  • Next



  • Section - Patches (for use with Conditional Undo by Jesse McGrew)

    Include (-
    [ Keyboard a_buffer a_table nw i w w2 x1 x2;
        sline1 = score; sline2 = turns;

        while (true) {
            ! Save the start of the buffer, in case "oops" needs to restore it
            for (i=0 : i<64 : i++) oops_workspace->i = a_buffer->i;
        
            ! In case of an array entry corruption that shouldn't happen, but would be
            ! disastrous if it did:
            #Ifdef TARGET_ZCODE;
            a_buffer->0 = INPUT_BUFFER_LEN;
            a_table->0 = 15; ! Allow to split input into this many words
            #Endif; ! TARGET_
        
            ! Print the prompt, and read in the words and dictionary addresses
            PrintPrompt();
            DrawStatusLine();
            KeyboardPrimitive(a_buffer, a_table);
        
            ! Set nw to the number of words
            #Ifdef TARGET_ZCODE; nw = a_table->1; #Ifnot; nw = a_table-->0; #Endif;
        
            ! If the line was blank, get a fresh line
            if (nw == 0) {
                @push etype; etype = BLANKLINE_PE;
                players_command = 100;
                BeginActivity(PRINTING_A_PARSER_ERROR_ACT);
                if (ForActivity(PRINTING_A_PARSER_ERROR_ACT) == false) L__M(##Miscellany,10);
                EndActivity(PRINTING_A_PARSER_ERROR_ACT);
                @pull etype;
                continue;
            }
        
            ! Unless the opening word was OOPS, return
            ! Conveniently, a_table-->1 is the first word on both the Z-machine and Glulx
        
            w = a_table-->1;
            if (w == (+ oops word #1 +) or (+ oops word #2 +) or (+ oops word #3 +)) {
                if (oops_from == 0) { L__M(##Miscellany, 14); continue; }
                if (nw == 1) { L__M(##Miscellany, 15); continue; }
                if (nw > 2) { L__M(##Miscellany, 16); continue; }
            
                ! So now we know: there was a previous mistake, and the player has
                ! attempted to correct a single word of it.
            
                for (i=0 : i<INPUT_BUFFER_LEN : i++) buffer2->i = a_buffer->i;
                #Ifdef TARGET_ZCODE;
                x1 = a_table->9; ! Start of word following "oops"
                x2 = a_table->8; ! Length of word following "oops"
                #Ifnot; ! TARGET_GLULX
                x1 = a_table-->6; ! Start of word following "oops"
                x2 = a_table-->5; ! Length of word following "oops"
                #Endif; ! TARGET_
            
                ! Repair the buffer to the text that was in it before the "oops"
                ! was typed:
                for (i=0 : i<64 : i++) a_buffer->i = oops_workspace->i;
                VM_Tokenise(a_buffer,a_table);
            
                ! Work out the position in the buffer of the word to be corrected:
                #Ifdef TARGET_ZCODE;
                w = a_table->(4*oops_from + 1); ! Start of word to go
                w2 = a_table->(4*oops_from); ! Length of word to go
                #Ifnot; ! TARGET_GLULX
                w = a_table-->(3*oops_from); ! Start of word to go
                w2 = a_table-->(3*oops_from - 1); ! Length of word to go
                #Endif; ! TARGET_
            
                ! Write spaces over the word to be corrected:
                for (i=0 : i<w2 : i++) a_buffer->(i+w) = ' ';
            
                if (w2 < x2) {
                    ! If the replacement is longer than the original, move up...
                    for (i=INPUT_BUFFER_LEN-1 : i>=w+x2 : i-- )
                        a_buffer->i = a_buffer->(i-x2+w2);
            
                    ! ...increasing buffer size accordingly.
                    #Ifdef TARGET_ZCODE;
                    a_buffer->1 = (a_buffer->1) + (x2-w2);
                    #Ifnot; ! TARGET_GLULX
                    a_buffer-->0 = (a_buffer-->0) + (x2-w2);
                    #Endif; ! TARGET_
                }
            
                ! Write the correction in:
                for (i=0 : i<x2 : i++) a_buffer->(i+w) = buffer2->(i+x1);
            
                VM_Tokenise(a_buffer, a_table);
                #Ifdef TARGET_ZCODE; nw = a_table->1; #Ifnot; nw = a_table-->0; #Endif;
                return nw;
            }

            ! Undo handling
        
            if ((w == (+ undo word #1 +) or (+ undo word #2 +) or (+ undo word #3 +)) && (nw==1)) {
                if (FollowRulebook( (+ before undoing an action rules +) ) && RulebookFailed())
                { continue; }
                Perform_Undo();
                continue;
            }
            if ( (+ prevent undo flag +) ) {return;}
            i = VM_Save_Undo();
            #ifdef PREVENT_UNDO; undo_flag = 0; #endif;
            #ifndef PREVENT_UNDO; undo_flag = 2; #endif;

            if ((+ save undo state +)) FollowRulebook( (+ report undo saving suspended rules +) );
            if (i == -1) undo_flag = 0;
            if (i == 0) undo_flag = 1;
            if (i == 2) {
                !FollowRulebook( (+ before undoing an action rules +) );
                VM_RestoreWindowColours();
                if ( FollowRulebook( (+ report undoing an action rules +) ) && RulebookFailed())
                {
                    VM_Style(SUBHEADER_VMSTY);
                    SL_Location(); print "^";
                    ! print (name) location, "^";
                    VM_Style(NORMAL_VMSTY);
                    L__M(##Miscellany, 13);
                }
                FollowRulebook( (+ after undoing an action rules +) );
                continue;
            }
            return nw;
        }
    ];
    -) instead of "Reading the Command" in "Parser.i6t".

    Include (-
    [ Perform_Undo;
        #ifdef PREVENT_UNDO;
        if ( FollowRulebook( (+ report prevented undo rules +) ) && RulebookFailed()) {
            L__M(##Miscellany, 70);
            }
        return;
        #endif;
        if (turns == 1) {
            FollowRulebook ( (+ before nothing to be undone failure rules +) );
            if ( FollowRulebook( (+ report nothing to be undone failure rules +) ) && RulebookFailed()) {
                L__M(##Miscellany, 11);
            }
            FollowRulebook ( (+ after nothing to be undone failure rules +) );
            return;
        }
        if (undo_flag == 0) {
            FollowRulebook ( (+ before interpreter-undo-incapacity rules +) );
            if ( FollowRulebook( (+ report interpreter-undo-incapacity rules +) ) && RulebookFailed()) {
                L__M(##Miscellany, 6);
            }
            FollowRulebook ( (+ after interpreter-undo-incapacity rules +) );
            return;
        }
        if (undo_flag == 1) {
            FollowRulebook ( (+ before interpreter undo failure rules +) );
            if ( FollowRulebook( (+ report interpreter undo failure rules +) ) && RulebookFailed()) {
                L__M(##Miscellany, 7);
            }
            FollowRulebook ( (+ after interpreter undo failure rules +) );
            return;
        }
        if (~~AllowUndo()) return;
        if (VM_Undo() == 0) {
            FollowRulebook ( (+ before interpreter undo failure rules +) );
            if ( FollowRulebook( (+ report interpreter undo failure rules +) ) && RulebookFailed()) {
            L__M(##Miscellany, 7);
            }
            FollowRulebook ( (+ after interpreter undo failure rules +) );
        }
    ];
    -) instead of "Perform Undo" in "OutOfWorld.i6t".