Glulx Input Loops

version 1/101121 by Erik Temple

  • Home page
  • Beginning
  • Previous



  • Chapter - Library replacement

    Include (-

    [ VM_KeyChar win nostat done res ix jx ch;
    #ifdef LOOP_DEBUG;
    print "***Warning: The I6 routine VM_KeyChar was called, providing an input loop intended for single-character input (char input). Be aware that VM_KeyChar is not controlled by Glulx Input Loops, and input handling options will not be as flexible. You can use the 'character input' input-loop for full support.^";
    #endif; ! LOOP_DEBUG
    jx = ch; ! squash compiler warnings
    if (win == 0) win = gg_mainwin;

    done = false;
    glk_request_char_event(win);
    while (~~done) {
    glk_select(gg_event);
    switch (gg_event-->0) {
    5: ! evtype_Arrange
    if (nostat) {
    glk_cancel_char_event(win);
    res = $80000000;
    done = true;
    break;
    }
    DrawStatusLine();
    2: ! evtype_CharInput
    if (gg_event-->1 == win) {
    res = gg_event-->2;
    done = true;
    }
    }
    ix = HandleGlkEvent(gg_event, 1, gg_arguments);
    if (ix == 2) {
    res = gg_arguments-->0;
    done = true;
    } else if (ix == -1) done = false;
    }

    return res;
    ];

    [ VM_KeyDelay tenths key done ix;
    #ifdef LOOP_DEBUG;
    print "***Warning: The I6 routine VM_KeyDelay was called, providing a timer-expired input loop intended for single-character input (char input). Be aware that VM_KeyDelay is not controlled by Glulx Input Loops, and input handling options will not be as flexible.^";
    #endif; ! LOOP_DEBUG
    glk_request_char_event(gg_mainwin);
    glk_request_timer_events(tenths*100);
    while (~~done) {
    glk_select(gg_event);
    ix = HandleGlkEvent(gg_event, 1, gg_arguments);
    if (ix == 2) {
    key = gg_arguments-->0;
    done = true;
    }
    else if (ix >= 0 && gg_event-->0 == 1 or 2) {
    key = gg_event-->2;
    done = true;
    }
    }
    glk_cancel_char_event(gg_mainwin);
    glk_request_timer_events(0);
    return key;
    ];

    [ VM_ReadKeyboard a_buffer a_table done ix;
    stored_buffer = a_buffer;
    #ifdef LOOP_DEBUG;
    print "^-->Starting the " ; style underline; print "main input"; style roman;
    print " loop (primary).^";
    #endif;
    (+ current input loop +) = (+ main input +);
    done = false;

    while (~~done) {
    ! Request line event should only be called if delegate event handling to parent loop
    ! is false--we don't want to do a line event request when the HandleGlkEvent rules might print text etc.
    if ( ~~(+ delegate event handling to parent loop +) ) {
    if ( FollowRulebook( (+ input loop setup rules +), (+ focal event type of main input +) ) == false) {
    glk_request_line_event(gg_mainwin, a_buffer+WORDSIZE, INPUT_BUFFER_LEN-WORDSIZE, 0);
    (+ line event pending +) = 1;
    }
    }
    if ( (+ delegate event handling to parent loop +) ) {
    #ifdef LOOP_DEBUG;
    print "-->Skipping to HandleGlkEvent on behalf of previous primary loop.";
    #endif; ! LOOP_DEBUG
    (+ delegate event handling to parent loop +) = false;
    jump HGEContinue;
    }
    #ifdef LOOP_DEBUG;
    print "-->Input requested ("; style underline; print "main input"; style roman;
    print "); focal event type of loop is ",
    (PrintEvType) (+ main input +).(+ focal event type +) ,".^";
    #endif;
    glk_select(gg_event);
    (+ current loop context +) = (+ g-primary +);
        #ifdef LOOP_DEBUG;
         print "-->Input received: ", (PrintEvType) gg_event-->0, "; consulting the input loop event-handling rules.^";
        #endif;
        if ( FollowRulebook( (+ input loop event-handling rules +), gg_event-->0 ) == false) {
    switch (gg_event-->0) {
    3: ! evtype_LineInput
    if (gg_event-->1 == gg_mainwin) {
    a_buffer-->0 = gg_event-->2;
    done = true;
    }
    }
    }
    (+ current input loop +) = (+ main input +);!Just in case the author has invoked another input loop from the input loop event-handling rules, we need to register that we are again running in main input.
    .HGEContinue;
    !(+ delegate event handling to parent loop +) = false;
    #ifdef LOOP_DEBUG;
    if ( ~~ (+ delegate event handling to parent loop +) ) {
    print "-->Consulting HandleGlkEvent from the primary loop " ;
    style underline; print "main input"; style roman; print ".^";
    }
    #endif;
    (+ delegate event handling to parent loop +) = false;
    ix = HandleGlkEvent(gg_event, gg_event-->0, a_buffer);
    if ( (+ delegate event handling to parent loop +) ) {
    #ifdef LOOP_DEBUG;
    print "-->Consulting HandleGlkEvent from within the primary loop " ;
    style underline; print "main input "; style roman;
    print "on behalf of the secondary loop ";
    style underline; print (PrintShortName) (+ current child loop +); style roman;
    print ".^";
    #endif; ! LOOP_DEBUG
         print "jumping.";
    jump HGEContinue; !A secondary input loop is running within the primary loop; repeat HandleGlkEvent, this time with the event array from the secondary event.
    }
    if (ix == 2) done = true;
    else if (ix == -1) done = false;
    if ( (+ line event pending +) == false && (+ main input +).(+ focal event type +) == 3) {
    !PrintPrompt();
    glk_request_line_event(gg_mainwin, a_buffer+WORDSIZE, INPUT_BUFFER_LEN-WORDSIZE, 0);
    (+ line event pending +) = true;
    }
    }

    VM_Tokenise(a_buffer,a_table);
    ! It's time to close any quote window we've got going.
    if (gg_quotewin) {
    glk_window_close(gg_quotewin, 0);
    gg_quotewin = 0;
    }
    #ifdef ECHO_COMMANDS;
    print "** ";
    for (ix=WORDSIZE: ix<(a_buffer-->0)+WORDSIZE: ix++) print (char) a_buffer->ix;
    print "^";
    #endif; ! ECHO_COMMANDS
    #ifdef LOOP_DEBUG;
    print "-->End the " ; style underline; print "main input"; style roman;
    print " input loop (primary).^";
    #endif; ! LOOP_DEBUG
    ];

    [ PrintEvType value;
    switch(value) {
    1: print "timer-event";
    2: print "char-event";
    3: print "line-event";
    4: print "mouse-event";
    5: print "arrange-event";
    6: print "redraw-event";
    7: print "sound-notify-event";
    8: print "hyperlink-event";
    default: print "<illegal g-event>";
    }
    ];

    -) instead of "Keyboard Input" in "Glulx.i6t".

    Include (- Global stored_buffer = 0 ; -) after "Definitions.i6t"

    To cancel line input in (win - a g-window), preserving keystrokes:
    (- glk_cancel_line_event({win}.ref_number, gg_event); stored_buffer-->0 = gg_event-->2; -)

    To re-request line input in (win - a g-window):
    (- glk_request_line_event({win}.ref_number, stored_buffer + WORDSIZE, INPUT_BUFFER_LEN - WORDSIZE, stored_buffer-->0); -)


    Glulx Input Loops ends here.