When you start up a Glulx interpreter, which we'll call "Glulxe" from here on out, your computer's operating system will set aside some amount of screen space for it. This could be just one window among many, as in Windows or the Mac; alternatively, it could be the entire screen, as in DOS, which only runs one program at a time. Either way, as far as the IF game itself is concerned, the space allocated to Glulxe is the entire world. The game is unaware of and cannot affect anything outside the Glulxe screen space.
Inside the Glulxe screen space is, at first, nothing. And nothing can be put there until a Glk window is opened. A Glk window is a portion of the Glulxe screen space which can display things and sometimes accept input. There are three types of windows the game programmer should know about:
The details of how to use each of these types of windows will be covered in later sections. The rest of this section will be concerned with how to create them and construct a customized window layout for your game.
Two windows are created by the library automatically (though this can be prevented using the InitGlkWindow() entry point. More on this shortly.) The first window is a text buffer window called "gg_mainwin", which fills the entire Glulxe screen space. This is then split into two, with a text grid window called "gg_statuswin" taking up one line at the top of the Glulxe screen space and gg_mainwin taking up the remainder.
If you want to add more windows, here's what you do. First, decide what sort of window it should be. Maybe you want a painted map of the game world to be permanently displayed on the screen. This would call for a graphics window. Next, select a name for the window. You can call it pretty much anything you want, but since the library starts all window names with "gg_", you might as well too. So we'll call it "gg_mapwin".
Next we need to come up with a "rock value" for this window. This should be a number 210 or greater. (If you don't know what a "rock value" is yet, don't be discouraged -- just pick a number 210 or greater (that you haven't already used for another window) and keep going.) For this example, we'll pick 210. The next step is to add a couple of lines to our code. In with your list of constants, put this line:
Constant GG_MAPWIN_ROCK 210;
and in with your list of global variables, put this line:
Global gg_mapwin = 0;
With those lines added to the code, we're now ready to actually create our new window. The key command here will be glk_window_open(). Inside the parentheses will go five parameters:
1) First, the name of the window to be split into two pieces. In this case, we're splitting the main window, so "gg_mainwin" would go here.
2) Next, the method we're using to split the windows. This is a two-part process. First, you need to pick one of the following four options:
Then, you need to pick one of the following choices:
Join these together with a plus sign. So, if we decide that we want the map to be permanently stationed on the left side of the Glulxe screen space, and we know the map is 240 pixels wide, we'd probably be inclined to go with "(winmethod_Left+winmethod_Fixed)". Where does the "240" go? Why, it goes in the...
3) ...third slot, where we put either: the number of lines or columns to be set aside for the new window (if it's a text window, and we picked winmethod_Fixed); the number of pixels to be set aside for the new window (if it's a graphics window, and we picked winmethod_Fixed); or, if we picked winmethod_Proportional, the percentage of the old window to be set aside for the new window (for instance, we'd put "50" if we wanted to divide the old window in half, or "33" if we wanted to set aside 1/3 of the old window's screen space for the new one to take over.)
4) Next up we put the type of window we want: wintype_TextBuffer, wintype_TextGrid, or wintype_Graphics. In this example, we want the last of these.
5) The last item in the list is the constant you declared earlier. In this case, that would be GG_MAPWIN_ROCK.
This leaves us with a call of:
gg_mapwin = glk_window_open(gg_mainwin, (winmethod_Left+winmethod_Fixed), 240, wintype_Graphics, GG_MAPWIN_ROCK);
Of course, just dropping a line like this into your program all by itself is a bad idea -- there are a number of conditions you need to check for. For one thing, before you open a window, you need to make sure the window isn't already open. Why would it be? Maybe the player has just restored a saved game (which does not automatically restore the window configuration from the time of the save: you need to take care of that yourself. How to do that will be explained shortly.) So let's wrap this up in a condition:
if (gg_mapwin == 0) { gg_mapwin = glk_window_open(gg_mainwin, (winmethod_Left+winmethod_Fixed), 240, wintype_Graphics, GG_MAPWIN_ROCK); }
Also, note that just because you request that a window be opened doesn't mean that it will be. The player may be using an interpreter which doesn't support graphics, for instance, in which case trying to open a graphics window is doomed to failure. Or maybe the interpreter does support graphics, but the player has set the entire Glulxe screen space to be less than 240 pixels wide, so the window you get is not exactly what you asked for. You'll certainly want to check for this sort of thing; what you actually do with the test results is up to you. For instance, if your game is incomprehensible without the graphics, then you'd want to test if the graphics window actually opened (with an "if (gg_graphics1win == 0)" type of test after your glk_window_open() call) and, if it didn't, print out a message like, "This game requires a graphics-capable interpreter. Sorry!" and make the game quit. But if the graphics are just a fun add-on, then you'd want to allow the game to continue, but just make sure that you never try to use glk_image_draw() to put an image in that (non-existent) window after failing to open it -- run a test every time.
To close a window, use the command glk_window_close(). This actually takes two arguments. The first is the name of the window to be closed. The second one is extremely esoteric; just put 0 and you'll be fine.