How are the TADS menus generated?

TADS menus are almost unusable in Parchment/Lectrote. For example: Dark Angle (enter Y then H).

The biggest problems is that the indicator for the current menu option is formatted with reverse mode, which isn’t yet supported by the Emglken port of TADS. IMO it would be much better if the menus were like Informs: Use a single > for the current option, and use spaces for the rest.

Now I’m going to work on adding reverse mode support to Emglken, but it will take some time. And even once I’ve done it, other Glk interpreters will also be affected by this problem.

My question for now is what actually generates these menus in this style?

  1. Is it the interpreter code itself? (That might actually be easier to modify than adding reverse mode support.)
  2. Is it the standard library? adv3 or adv3lite?
  3. Is it an additional library?

If the problem is one of the libraries, what would the process be to fix the library so that it is more reliable (such as borrowing Inform’s menu style)?

I know there’s three adv3 source files devoted to menus (which I haven’t looked much into yet) but that would probably be the place to look first… menusys.t, menucon.t, and maybe another…

I don’t believe so. As @johnnywz00 said, there’s three source files that implement the menu system: menusys.t (base classes), menucon.t (subclasses for console/HTML interpreters), and menuweb.t (for web-based TADS, I don’t think you need to worry about that).

Now, those classes do rely on the Banner API to some degree as part of the menu display, placing the menus’ topmost title and some key help in the status line. I believe the Banner API is ultimately implemented by the interpreter.

The above three files are in both adv3 and adv3Lite. The adv3Lite docs on menus claim its system “is identical to the adv3 module of the same name,” but I haven’t done a diff to verify that. (I would think any differences are minor. When I tried the INSTRUCTIONS command on both libraries, it looked and operated fundamentally the same with both.)

When I run a TADS 3 game with FrobTADS and QTads, the menus display a single > for the cursor and blanks everywhere else, with no reversed characters.

At least I thought that until I noticed in the code this being done:

  *   To get the alignment right, we have to print '>' on
  *   each and every line. However, we print it in the
  *   background color to make it invisible everywhere but
  *   in front of the current selection.
if (selection != i)
    "<font color=<<bgcolor>> >&gt;</font>";

Perhaps that’s what you’re seeing, the > ("&gt;") being printed in the background color in order to hide it?

To make sure we’re on the same page, my understanding is that FrobTADS is considered an HTML interpreter even though it’s a console/terminal application. It’s “HTML-aware.” So, I believe it and QTads are executing the above code.

An HTML-aware interpreter will “eat” extraneous whitespace. (Actually, I think all TADS interpreters do that, but let’s set that aside for the moment.) The above trick ensures the menu text is left-aligned down the screen, with the visible > cursor moving up and down to their immediate left.

I don’t know who, if anyone, is maintaining the libraries at the moment. More importantly, updating the libraries today won’t fix all the compiled TADS games already out there with this behavior. If I’m right and the above code is the issue, perhaps it can be easily worked around by the interpreters?

– Jim


Gargoyle displays it like this:
screenshot from Gargoyle

So I guess not only should we be looking at improving Emglken, but there might be more to do in the Glk port so that it can properly hide the other >s like intended.

Thanks for the info!

1 Like

It’s implemented by the interpreter. For text-only interpreters, the os_banner* set of functions is responsible for menus.

Is Parchment using this implementation:

Or the no-op one that doesn’t actually do anything:

Don’t the banner functions control the upper/status window? But the > options are in the lower window.

Edit: Or do the banner functions control all additional windows? It looks like it creates two windows, pop-over style (which might be causing some of the GlkOte problems.) But the content, including the >s, isn’t in the banner functions as far as I can see.

(Also, it’s odd that the top window is a buffer window. Shouldn’t it be a grid window? And it is a grid window in Gargoyle, so I’m not sure what’s different, it should be the same in Emglken!)

The menu system creates a banner window that takes up all available space. This reduces the main window to a size of zero, basically.

The adv3 menu system doesn’t create text grid banners. Only normal ones. Some have the OS_BANNER_STYLE_TAB_ALIGN set. Gargoyle switches to a fixed-width font for banners that have that flag set. Parchment doesn’t seem to do that, which probably explains why the score isn’t aligned correctly.

Btw, the actual contents of the banners are obviously done by the game. When I said that “it’s implemented by the interpreter,” I only meant the banner implementation. If you add inverse color support, it should make Parchment behave like Gargoyle.

Edit: Not sure if what’s needed is just inverse color support, or color support in general. Adv3 simply draws > characters in front of all menu items, but only uses the foreground color for the one in front of the currently selected item. For all others, it sets the foreground color to be the same as the background color.

1 Like

Ah, interesting. This should give me enough to go digging and find out what I need to do to also switch to fixed width font.

OK, it seems Parchment doesn’t do colors at all. The status line of this game for example should be red, but it isn’t:

It’s red in Gargoyle.

So yeah, you definitely need color support to get TADS menus working nicely :slight_smile:

There are so many things to fix :wink: If I can get TADS to make text grid windows (and I think it does for TADS 2? It does in osglkban.c) then that will be best. But if it uses stylehints, then that’s a lot more work, because RemGlk doesn’t support them at all. And I had hoped that it might be using the Garglk reverse mode extension function, but it doesn’t. So I guess stylehints it is!

You can use the sample game that comes with the Tads 3 sources. In garglk, it’s in terps/tads/tads3/samples. You can modify bantest.t and replace BannerTypeText with BannerTypeTextGrid so it makes grid banners.

Then mkdir obj and build with t3make -f sample.t3m to get sample.t3. Use the addban, addsub and delban to add/remove banners, and writeban to print text in a banner.

For example, this adds a banner on the right side of the window:

addban right r

This adds a sub-banner to the bottom of it:

addsub r bottom b

Print something in the bottom banner:

writeban b Hello world.

Have you looked at how this is done in Spatterlight? As usual, the code is messy, but it seems to work correctly in most games.

1 Like

Wow, that doesn’t look too complex at all!

It would be real nice if there was an upstream TADS repo these changes could be made in, so we could all more easily benefit from them.

Maybe it’s time we just start one.


The actual text color functionality was added here, by the way.

EDIT: The current TADS Glk code used in Gargoyle and Spatterlight closes and re-creates the status banner window on every turn in order to be able to change text colors and styles, because in the Glk model, changes to styles won’t be visible in already existing windows. The could probably be simplified a lot by using your Glk Z-colors instead, which were specifically created to be able to change colors on the fly.

I set up an org: Unofficial TADS Github organisation

If you have any spare time and wanted to add your improvements (if they don’t depend on Spatterlight specific code), that would be awesome!

I’ve added stylehint support to Emglken/Parchment (but not the Garglk extensions), which is making some TADS status windows/menus better, and others worse…

Edit: I’ve figured out the cause of one problem, but am not sure on the best solution yet: If Glk can't measure colours, should not set foreground and background to the same colour · Issue #3 · tads-intfic/tads-runner · GitHub

Well it’s a work in progress. The black on black is now fixed, and the currently option is highlighted meaningfully, but now the top window thinks that it is wider than it really is. I guess this is because the monospaced character width is wider than the proportional font width?

1 Like

So I’ve got two solutions to the banner window issue. To recap, As RealNC explained above, TADS normally doesn’t make actual grid windows, but instead makes “tab aligned” windows, which use fixed width fonts. This is a problem for most Glk interpreters as the width of the window will be measured with proportional width fonts, and so when it tries to print a full line, it can be too long for each line. Some more discussion on Github:

The first PR switches to an actual Glk grid window if the OS_BANNER_STYLE_TAB_ALIGN style is used.

The second PR fixes the measuring of windows, by measuring the width of a temporary grid window instead of the actual buffer window. However this requires certain styling options: both grid and buffer windows must use the same font size (Parchment currently has 15px for buffer but only 14px for grid), the same window paddings/margins, and grid windows must reserve space for a scrollbar, even though they never use a scrollbar.

The first option is safer: by using a real Glk grid window it ensures that the width will always be correct, the font will always fit it, etc. The second does seem to work, but it does introduce constraints. For example, on a mobile screen forcing the grid and buffer windows to have the same font size is probably non-ideal, as a smaller or more narrow font for the status window would allow more to be shown in it.

There’s one situation I think of which would mean the second option is better: if tab aligned windows are still intended to be scrolled when you write too much to them. Grid windows can’t be scrolled; if you write too much then anything extra is just lost to the ether. If that is a problem for TADS, then the second solution is better. But if authors aren’t expecting the windows to be scrollable, then I think the first solution is more foolproof.

1 Like

This is decided by the game author. Banners can have flags set that make them auto-scroll when new text is added, and they can also have horizontal or vertical scroll bars.

See the different OS_BANNER_STYLE flags in tads2/osifc.h on the interpreter side, and the BannerStyle flags in tads3/include/tadsio.h on the game side.


One more PR, which I think should now be the most reliable option:

It now looks both for the OS_BANNER_STYLE_TAB_ALIGN banner mode, as well as some scrolling modes (OS_BANNER_STYLE_VSCROLL, OS_BANNER_STYLE_AUTO_VSCROLL, OS_BANNER_STYLE_MOREMODE). If the window is tab aligned and doesn’t need to be scrolled, then it uses a Glk grid window. If it’s tab aligned and one or more of those scrolling modes is enabled, then it uses a Glk banner window, but sets all the fonts to be fixed width. From my tests this seems to work, though that’s because I haven’t found any games yet that want scrollable banners.