Tracking down strange order of glulxe events (updated: Inform IDE gives wrong hyperlink ID number?)

Continuing the discussion from A request for assistance: hyperlinks in lists (GEP probably?):

I’ve decided to try to track down this odd behavior from Glulx entry points and lists, where SAYing or REPEATing THROUGH a list of hyperlinked texts will work just fine, except that the final hyperlink will crash.

I tried removing all material from my extension to isolate what happens. I tried only copying and pasting the important bits of Glulx Entry Points to track down the behavior.

Most recently, I tried to determine exactly what Glulx event requests are happening when clicking on hyperlinks.

In the IDE, this is what we get:

But Quixe is more forgiving and lets us get away with some illegal events. This is what we get there:

To get this code dump, this is the code I inserted into Glulx Entry Points:


glk-event-list is a list of text that varies.

To decide what number is the value returned by glk event handling (this is the handle glk event rule):
	now glulx replacement command is "";
	add the substituted form of "[current glk event]" to glk-event-list;
	follow the glulx input handling rules for the current glk event;
	if the outcome of the rulebook is the replace player input outcome:
		decide on input replacement;
	if the outcome of the rulebook is the require input to continue outcome:
		decide on input continuation;
	follow the command-counting rules;
	if the rule succeeded:
		follow the input-cancelling rules;
		follow the command-showing rules;
		follow the command-pasting rules;
		if the [command-pasting] rule succeeded:
			decide on input replacement;

Every turn:
	say "The glk event list is [glk-event-list]".

(my lines are those involving glk-event-list)

Interestingly, if instead of printing ‘every turn’ we print at the beginning or end of the ‘to decide’ phrase, we reproduce the crash for every hyperlink.

To be clear, I don’t believe this is code in Simple Multimedia Effects causing this. I included a large chunk of VM keyboard replacement code to handle ‘echoing’, but deleting all of that has no effect on crashing.

This is the full text of the hyperlink code (which I believe was originally written by Petter Sjölund, as that’s who I credit)

A glulx hyperlink rule (this is the default inline hyperlink handling rule):
	now the current hyperlink ID is the link number of the selected hyperlink;
	unless the current hyperlink ID is 0:
		cancel glulx hyperlink request in main window;[just to be safe]
		cancel glulx hyperlink request in status window;[just to be safe]
		follow the hyperlink processing rules;
	if the status window is the hyperlink source:
		request glulx hyperlink event in status window;
	otherwise:
		request glulx hyperlink event in main window.

To request glulx hyperlink event in the/-- main window:
	(-  if (glk_gestalt(gestalt_Hyperlinks, 0)) glk_request_hyperlink_event(gg_mainwin); -)

To cancel glulx hyperlink request in the/-- main window:
	(-  if (glk_gestalt(gestalt_Hyperlinks, 0)) glk_cancel_hyperlink_event(gg_mainwin); -)

To request glulx hyperlink event in the/-- status window:
	(-  if (glk_gestalt(gestalt_Hyperlinks, 0)  && gg_statuswin) glk_request_hyperlink_event(gg_statuswin); -)
	
To cancel glulx hyperlink request in the/-- status window:
	(-  if (glk_gestalt(gestalt_Hyperlinks, 0) && gg_statuswin) glk_cancel_hyperlink_event(gg_statuswin); -)

To decide whether the status window is the hyperlink source:
	(- (gg_event-->1==gg_statuswin) -)

To decide which number is the link/-- number of the/-- selected/clicked hyperlink:
	(- (gg_event-->2) -)

Section 3 - Placing links

The hyperlink list is a list of texts that vary..

To hyperlink (hyper-text - a text) as (hyper-command - a text):
	let hyperlink index be a number;
	if the hyper-command is listed in the hyperlink list:
		repeat with count running from 1 to the number of entries in the hyperlink list:
			if entry (count) of the hyperlink list is hyper-command:
				let hyperlink index be count;
	otherwise unless the hyper-command is "":
		add hyper-command to hyperlink list;
		let hyperlink index be the number of entries of hyperlink list;
	say "[set link (hyperlink index)][hyper-text][terminate link]";
		 
To say set link (N - a number):
	(-  if (glk_gestalt(gestalt_Hyperlinks, 0)) glk_set_hyperlink({N}); -)

To say terminate link:
	(-  if (glk_gestalt(gestalt_Hyperlinks, 0)) glk_set_hyperlink(0); -)

Section 4 - Processing hyperlinks

The hyperlink processing rules are a rulebook.

The current hyperlink ID is a number that varies.

Section 5 - Selecting replacement command

A hyperlink processing rule (this is the default command replacement by hyperlinks rule):  
	now the glulx replacement command is entry (current hyperlink ID) of the hyperlink list;
	rule succeeds.
2 Likes

Putting this in a reply to make it stand out more, I wonder if anyone has a suggestion on what an ‘illegal g-event’ might be? Or why ‘arrange-event’ is being called?

Edit: Okay, I figured it out, it was because I opened the console which resized the window. Post 5 has the correct order of events. So it looks like ‘weird call’ is a dead end. But posts 4 and 5 show how the error described is different between Quixe and the Inform 7 IDE.)

It shouldn’t be, though! The GlkOte library explicitly checks for this error (“Got content update for window …, which is awaiting line input.”)

1 Like

Interesting. Looking at the windows IDE github code, the code that triggers this check is:

void I7GlkWinStream::putStr(char* s, glui32 len, bool check)
{
  if (check && m_win->inputActive())
  {
    fatalError("Printing text to a window that is waiting for line or character input is not allowed.");
    return;
  }

I’ll look at the GlkOte library and compare. It’s possible that the Windows IDE is catching a different problem and just categorizing it wrong.

Looking at the GEP code, is it possible that the enumeration of Glulx events doesn’t match the actual glulx events being passed by Inform 10? Like a new type was added or something? I’m not sure how we’d get ‘illegal g-event’ otherwise.

The g-events are timer-event, char-event, line-event, mouse-event, arrange-event, redraw-event, sound-notify-event, and hyperlink-event.

Hmm, maybe it’s character input specifically, since your code is:

function accept_one_content(arg) {
    const win = windowdic.get(arg.id);

    /* Check some error conditions. */

    if (win == null) {
        glkote_error('Got content update for window ' + arg.id + ', which does not exist.');
        return;
    }

    if (win.input && win.input.type == 'line') {
        glkote_error('Got content update for window ' + arg.id + ', which is awaiting line input.');
        return;
    }

but the Inform IDE code just checks if the window has input active.

So the error must come from some action that makes a window have active input but isn’t classified as a line event.

Edit: Ah, okay, the ‘arrange’ event was from me opening the console while the window was open (so was the illegal event). So that has nothing to do with all of this.

This is the correct picture of events:

Further edit:

Changing the Quixe code to get rid of && win.input.type == 'line' should throw an error any time we try to print to a window with any type of input active. But it throws no errors here. Maybe this is a bug exclusive to WinIDE? I’ll try gargoyle next.

Editeditedit: Looks like it works just fine in gargoyle.

Okay, looking more into this, I found that the thing that was crashing the IDE was an invalid list number.

I added a tracker to my code:


Bad hyperlink ID is a list of numbers that varies.

When play begins:
	add 5 to bad hyperlink ID;

A hyperlink processing rule (this is the default command replacement by hyperlinks rule): 
	let temp be the number of entries in the hyperlink list;
	unless current hyperlink ID < temp:
		add current hyperlink ID to bad hyperlink ID;
		now current hyperlink ID is 1;
	now the glulx replacement command is entry (current hyperlink ID) of the hyperlink list;
	rule succeeds.

Every turn:
	say "hello!";
	say hyperlink list;
	say line break;
	say current hyperlink ID;
	say line break;
	say bad hyperlink ID;

and now the game compiles just fine, and here’s the output (the third link is what usually crashes, but only the IDE):

And here’s the result in Quixe/Bisquixe:

‘Current hyperlink ID’ and ‘hyperlink list’ are terms defined in the same extension:

The hyperlink list is a list of texts that vary.

To hyperlink (hyper-text - a text) as (hyper-command - a text):
	let hyperlink index be a number;
	if the hyper-command is listed in the hyperlink list:
		repeat with count running from 1 to the number of entries in the hyperlink list:
			if entry (count) of the hyperlink list is hyper-command:
				let hyperlink index be count;
	otherwise unless the hyper-command is "":
		add hyper-command to hyperlink list;
		let hyperlink index be the number of entries of hyperlink list;
	say "[set link (hyperlink index)][hyper-text][terminate link]";
A glulx hyperlink rule (this is the default inline hyperlink handling rule):
	now the current hyperlink ID is the link number of the selected hyperlink;
	unless the current hyperlink ID is 0:
		cancel glulx hyperlink request in main window;[just to be safe]
		cancel glulx hyperlink request in main window;[just to be safe]
		follow the hyperlink processing rules;
	if the status window is the hyperlink source:
		request glulx hyperlink event in status window;
	otherwise:
		request glulx hyperlink event in main window.

And ‘selected hyperlink’ and ‘link number’ are not defined in any extensions I have, they must be some core Inform thing.

Edit:
With Zed’s help, it turns out those terms are in the extension:

To decide which number is the link/-- number of the/-- selected/clicked hyperlink:
    (- (gg_event-->2) -)

After more time, it looks like it’s just a rare event where the Inform IDE gives the wrong first value for the ‘event’ type object. I used some code to ‘catch’ stray events and their values and there is only a single event happening (a hyperlink event) with a single value (1049). And it only happens if saying lists of 3 hyperlinks, not 4, which is fun.

I doubt very many people are reading this thread, but if anyone finds a crashing error with Bisquixe outside of the Inform IDE and outside of this buffer issue (Bisquixe problem with hyperlinks (input buffer message)), let me know so I can work more to track this down!

Zed helped me figure out a lot of these things.

1 Like

Checking back: the Inform IDE is too strict here. The spec says “It is illegal to print anything to a window which has line input pending.” Printing during character input or hyperlink input should be okay.

5 Likes

Checking in to say that David Kinder tracked this down and confirmed it’s a bug in the Inform IDE, not in Bisquixe, and has a fix pushed to GitHub. So that should take care of that problem in the next release!

3 Likes

Oh nice! Do you have a link to the bug report? I’d love to hear how this happened.

1 Like

It’s listed here:

The commit itself is here:

I’m not savvy enough in C++ to know what went wrong originally, but it looks like he reformatted how links are stored. I’m glad there’s a good team who knows all this stuff!

1 Like