Has anyone worked with text stream inclusions in I7 6L02?

I’ve run into a snag converting Conversation Builder to 6L02. This extension is much more Emily’s code still, especially the I6. And the latter is largely midsize-to-giant functions full of GLK opcodes which I have no idea what they do. GLK was updated with this version of Inform, wasn’t it?

Oh, and the whole CB extension is currently available from the extensions github.

First, external file writing doesn’t work, and it didn’t even in 6G06, and I’m not sure why. I know Kerkerkruip does external writing properly, but I haven’t looked at its code; maybe I should try to replace the system with a native I7 one? But I’d have to do it all at once, since I don’t know I6 well enough to disentangle each function piecemeal.

The main issue, though, is in the process of writing new dialog, the system saves it all in one big text stream, which is supposed to be printed out when you say “SHOW SOURCE”, not only printed to the external file. But that’s giving me runtime errors in 6L02.

The L# are debugging aids I’ve added to demarcate each line of the output.

The code in question: Carry out looking at new source (this is the source examination rule): say "You review your new code: [paragraph break]" (A); repeat with N running from 1 to file line count: say "L[N]: "; draw big buffer from line N of file "NewConversation"; say big buffer; say line break.
The big buffer lines are merely: To draw big buffer from line (N - a number) of file (S - some text): (- AcquireArrayFromFile({S}, big_big_buffer, {n}); -) and To say big buffer: (- CharBufferDump(big_big_buffer); -)
Looks like it may be a problem with CharBufferDump, but that’s just [ CharBufferDump array_name length maxlen i; maxlen = STRING_BUFFER_SIZE; if (length == 0) length = array_name-->0; for (i=0:i<array_name-->0 && i<length:i++ ) { ! print (i+WORDSIZE), ":"; if (array_name->(i+WORDSIZE) < 127 && array_name->(i+WORDSIZE) > 31) print (char) array_name->(i+WORDSIZE); } ];
I see elsewhere online this message can be fixed by replacing print() with PrintText(), but that doesn’t work in this case thanks to the array_name->(i+WORDSIZE); afterwards.

And if the problem isn’t in that function I suspect it may lie in StuffBuffer, which I have no idea where to even start debugging:

[rant] [ StuffBuffer a_buffer done ix i; if (gg_commandstr ~= 0 && gg_command_reading ~= false) { ! get_line_stream done = glk($0091, gg_commandstr, a_buffer+WORDSIZE, LARGE_BUFFER_LENGTH-WORDSIZE); if (done == 0) { glk($0044, gg_commandstr, 0); ! stream_close gg_commandstr = 0; gg_command_reading = false; ! L__M(##CommandsRead, 5); would come after prompt ! fall through to normal user input. } else { ! Trim the trailing newline if ((a_buffer+WORDSIZE)->(done-1) == 10) done = done-1; a_buffer-->0 = done; glk($0086, 8); ! set input style glk($0084, a_buffer+WORDSIZE, done); ! put_buffer glk($0086, 0); ! set normal style print "^"; jump KPContinue; } } done = false; glk($00D0, gg_mainwin, a_buffer+WORDSIZE, LARGE_BUFFER_LENGTH-WORDSIZE, 0); ! request_line_event while (~~done) { glk($00C0, gg_event); ! select switch (gg_event-->0) { 5: ! evtype_Arrange DrawStatusLine(); 3: ! evtype_LineInput if (gg_event-->1 == gg_mainwin) { a_buffer-->0 = gg_event-->2; done = true; } } ix = HandleGlkEvent(gg_event, 0, a_buffer); if (ix == 2) done = true; else if (ix == -1) done = false; } if (gg_commandstr ~= 0 && gg_command_reading == false) { ! put_buffer_stream glk($0085, gg_commandstr, a_buffer+WORDSIZE, a_buffer-->0); glk($0081, gg_commandstr, 10); ! put_char_stream (newline) } .KPContinue; for (i = WORDSIZE : i <= (a_buffer-->0)+(WORDSIZE-1) : i++) { if ((a_buffer->i) == '"') { a_buffer->i = 39; } } WriteArrayToFile("NewConversation", a_buffer, 1); ];[/rant]

Oh, now this is interesting. On a lark I uncommented the line ! print (i+WORDSIZE), ":"; , which prints a number before each character printed by the CharBufferDump routine:

So, that means the error message was provoked at the read/write stage, written to the charstream correctly, and then read out—again correctly—upon user request. So that leads me back to StuffBuffer.

Glk functions were added but that shouldn’t affect text.

This almost certainly means you passed an I7 text object to a function that expects an I6 string object. They used to be the same; now they’re different.

Great! Thanks to you and the 6L02 changelog, I realized it was a one line change from print (string) new_str; to TEXT_TY_Say(new_str); in the WriteTextToFile function.

New, closely related problem:

That sample new quip I was building before is now input and built and displayed properly… except for the quoted text:

The relevant function: To get text for a quoted field: write quotemark after file "NewConversation"; stuff buffer; write quotemark after file "NewConversation";
And so once more—and this time for certain—I’m back at StuffBuffer. Time to start spewing print statements throughout…

Hmm. It’s difficult to distinguish whether reading the input failed, or it just didn’t get saved properly in the char array.

But the problem seems to be the former:

That “read” is a debug line. It prints the contents of the the array that was read in from the player input the line before: nothing, apparently.

I think it comes down to these definitions:Array big_big_buffer -> LARGE_BUFFER_LENGTH; Array big_content_buffer -> LARGE_BUFFER_LENGTH;
(which the 6L02 changelog suggests should be changed to “Array buffer → PACKED_TEXT_STORAGE EMPTY_TEXT_PACKED;”, maybe. That alone doesn’t fix it, though.) and something in this block, from StuffBuffer, that reads in player input (since text was rejiggered in 6L02, and input doesn’t seem to be working using the old code): [rant] done = false; glk($00D0, gg_mainwin, a_buffer+WORDSIZE, LARGE_BUFFER_LENGTH-WORDSIZE, 0); ! request_line_event while (~~done) { glk($00C0, gg_event); ! select switch (gg_event-->0) { 5: ! evtype_Arrange DrawStatusLine(); 3: ! evtype_LineInput if (gg_event-->1 == gg_mainwin) { a_buffer-->0 = gg_event-->2; done = true; } } ix = HandleGlkEvent(gg_event, 0, a_buffer); if (ix == 2) done = true; else if (ix == -1) done = false; }[/rant]
Hmm… from further study, when gg_event is the LineInput event, that means the player hit ‘return’. And if I understand the syntax of “a_buffer–>0 = gg_event–>2;”, it’s basically setting the length of the a_buffer text (i.e., char array—or so it was in 6G06—hmm…) to the length of what was input. And it’s the “glk($00D0, gg_mainwin, a_buffer+WORDSIZE, LARGE_BUFFER_LENGTH-WORDSIZE, 0); ! request_line_event” line that actually reads in the input from the player and stores it in a_buffer.

So. I’m thinking I need to do this in a more I7ish way, because texts aren’t char arrays any more. (And they need to be texts, in order to be input from within I7. (I think.)) But I don’t know how that should be.

I think you still read in text as a char array, using the same code as before. Then you convert the array to an I7 text object. I have not yet figured out how to do that conversion, however.

Correct. The format of the buffer array hasn’t changed.

Thing is, this reading in is what seems to not be working for me. The last two lines here are debug:

[rant] done = false; glk($00D0, gg_mainwin, a_buffer+WORDSIZE, LARGE_BUFFER_LENGTH-WORDSIZE, 0); ! request_line_event while (~~done) { glk($00C0, gg_event); ! select switch (gg_event-->0) { 5: ! evtype_Arrange DrawStatusLine(); 3: ! evtype_LineInput if (gg_event-->1 == gg_mainwin) { a_buffer-->0 = gg_event-->2; done = true; } } ix = HandleGlkEvent(gg_event, 0, a_buffer); if (ix == 2) done = true; else if (ix == -1) done = false; } print "read: "; PrintI6Text(a_buffer-WORDSIZE);[/rant]
But only the "read: " line prints anything. a_buffer seems to be empty.

a_buffer-WORDSIZE is the word before the array. Shouldn’t it just be a_buffer or a_buffer+WORDSIZE?

Oh, I’ve tried all three in PrintI6Text(); nothing prints.

PrintI6Text does not work on character arrays. It works on I6 string objects.

You need to crawl down the array printing characters one at a time.

Aha. So thanks to your inputeventtext.inf, I have that working:

But then it’s not being stored in the file properly.

The function being called to do that, which worked in 6G06, is: [ WriteArrayToFile file_name array_name append_flag fref length str i maxlen mode; fref = glk_fileref_create_by_name(fileusage_Data+fileusage_BinaryMode, Glulx_ChangeAnyToCString(file_name), 0); if (append_flag) mode = filemode_WriteAppend; else mode = filemode_Write; str = glk_stream_open_file(fref, mode, 0); glk_stream_set_current(str); maxlen = STRING_BUFFER_SIZE; for (i=0:i<array_name-->0 && i<maxlen:i++ ) { print (char) array_name->(i+WORDSIZE); } glk_set_window(gg_mainwin); glk_stream_close(str, 0); ];

But that’s just simple print, which hasn’t changed…

Is the file being opened and closed empty, or does it not get updated at all? Timestamp change on the file? I’m thinking maybe the file name is being handed in wrong, so the wrong file gets written.

Oh wow. I just searched for NewConversation in my Inform folder, and it turns out NewConversation.glkdata was lurking in the top-level Inform/Projects folder. I guess I never scrolled down enough there to find it.

Thing is, that’s full of all of the big stuffed buffers concatenated together from the beginning of time, while there’s a second file, null.glkdata, containing the actual set of quips being built in each run through:

[code]for directions is a questioning quip. The comment is “”.

It mentions .
The reply is “”.

[/code]
So, ironically enough, however the StuffBuffer routine is opening the file, now it’s the only function doing it correctly. Now to figure out why that is exactly…

Of course, it turns out to be simple: the filename was being sent from the I7 layer, which no longer stores text in the same format as I6, so I6 didn’t know what to do with it. Since that name never changes anyway, I’ve just hardcoded it in I6, at least for now.