+/**
+ * glk_window_clear:
+ * @win: A window.
+ *
+ * Erases the window @win. The meaning of this depends on the window type.
+ *
+ * <itemizedlist>
+ * <listitem><para>
+ * Text buffer: This may do any number of things, such as delete all text in
+ * the window, or print enough blank lines to scroll all text beyond
+ * visibility, or insert a page-break marker which is treated specially by the
+ * display part of the library.
+ * </para></listitem>
+ * <listitem><para>
+ * Text grid: This will clear the window, filling all positions with blanks.
+ * The window cursor is moved to the top left corner (position 0,0).
+ * </para></listitem>
+ * <listitem><para>
+ * Graphics: Clears the entire window to its current background color.
+ * </para></listitem>
+ * <listitem><para>
+ * Other window types: No effect.
+ * </para></listitem>
+ * </itemizedlist>
+ *
+ * It is illegal to erase a window which has line input pending.
+ */
+void
+glk_window_clear(winid_t win)
+{
+ g_return_if_fail(win != NULL);
+ g_return_if_fail(win->input_request_type != INPUT_REQUEST_LINE && win->input_request_type != INPUT_REQUEST_LINE_UNICODE);
+
+ switch(win->type)
+ {
+ case wintype_Blank:
+ /* do nothing */
+ break;
+
+ case wintype_TextBuffer:
+ /* delete all text in the window */
+ {
+ gdk_threads_enter();
+
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(win->widget) );
+ GtkTextIter start, end;
+ gtk_text_buffer_get_bounds(buffer, &start, &end);
+ gtk_text_buffer_delete(buffer, &start, &end);
+
+ gdk_threads_leave();
+ }
+ break;
+
+ default:
+ g_warning("glk_window_clear: unsupported window type");
+ }
+}
+
+/**
+ * glk_set_window:
+ * @win: A window.
+ *
+ * Sets the current stream to @win's window stream. It is exactly equivalent to
+ * <informalexample><programlisting>
+ * glk_stream_set_current(glk_window_get_stream(win))
+ * </programlisting></informalexample>
+ */
+void
+glk_set_window(winid_t win)
+{
+ glk_stream_set_current( glk_window_get_stream(win) );
+}
+
+/**
+ * glk_window_get_stream:
+ * @win: A window.
+ *
+ * Returns the stream which is associated with @win. Every window has a stream
+ * which can be printed to, but this may not be useful, depending on the window
+ * type. (For example, printing to a blank window's stream has no effect.)
+ *
+ * Returns: The window stream.
+ */
+strid_t glk_window_get_stream(winid_t win)
+{
+ g_return_val_if_fail(win != NULL, NULL);
+ return win->window_stream;
+}
+
+/**
+ * glk_window_set_echo_stream:
+ * @win: A window.
+ * @str: A stream to attach to the window, or %NULL.
+ *
+ * Attaches the stream @str to @win as a second stream. Any text printed to the
+ * window is also echoed to this second stream, which is called the window's
+ * "echo stream."
+ *
+ * Effectively, any call to glk_put_char() (or the other output commands) which
+ * is directed to @win's window stream, is replicated to @win's echo stream.
+ * This also goes for the style commands such as glk_set_style().
+ *
+ * Note that the echoing is one-way. You can still print text directly to the
+ * echo stream, and it will go wherever the stream is bound, but it does not
+ * back up and appear in the window.
+ *
+ * It is illegal to set a window's echo stream to be its own window stream,
+ * which would create an infinite loop. It is similarly illegal to create a
+ * longer loop (two or more windows echoing to each other.)
+ *
+ * You can reset a window to stop echoing by setting @str to %NULL.
+ */
+void
+glk_window_set_echo_stream(winid_t win, strid_t str)
+{
+ g_return_if_fail(win != NULL);
+
+ /* Test for an infinite loop */
+ strid_t next = str;
+ for(; next && next->type == STREAM_TYPE_WINDOW; next = next->window->echo_stream)
+ {
+ if(next == win->window_stream)
+ {
+ g_warning("%s: Infinite loop detected", __func__);
+ win->echo_stream = NULL;
+ return;
+ }
+ }
+
+ win->echo_stream = str;
+}
+
+/**
+ * glk_window_get_echo_stream:
+ * @win: A window.
+ *
+ * Returns the echo stream of window @win. If the window has no echo stream (as
+ * is initially the case) then this returns %NULL.
+ *
+ * Returns: A stream, or %NULL.
+ */
+strid_t
+glk_window_get_echo_stream(winid_t win)
+{
+ g_return_val_if_fail(win != NULL, NULL);
+ return win->echo_stream;
+}
+
+/**
+ * glk_window_get_size:
+ * @win: A window.
+ * @widthptr: Pointer to a location to store the window's width, or %NULL.
+ * @heightptr: Pointer to a location to store the window's height, or %NULL.
+ *
+ * Simply returns the actual size of the window, in its measurement system.
+ * Either @widthptr or @heightptr can be %NULL, if you only want one
+ * measurement. (Or, in fact, both, if you want to waste time.)
+ */
+void
+glk_window_get_size(winid_t win, glui32 *widthptr, glui32 *heightptr)
+{
+ g_return_if_fail(win != NULL);
+
+ /* TODO: Write this function */
+ /* For a text buffer window: Return the number of rows and columns which
+ would be available _if_ the window was filled with "0" (zero) characters in
+ the "normal" font. */
+ if(widthptr != NULL) {
+ *widthptr = 0;
+ }
+
+ if(heightptr != NULL) {
+ *heightptr = 0;
+ }
+}
+
+/**
+ * glk_window_move_cursor:
+ * @win: A text grid window.
+ * @xpos: Horizontal cursor position.
+ * @ypos: Vertical cursor position.
+ *
+ * Sets the cursor position. If you move the cursor right past the end of a
+ * line, it wraps; the next character which is printed will appear at the
+ * beginning of the next line.
+ *
+ * If you move the cursor below the last line, or when the cursor reaches the
+ * end of the last line, it goes "off the screen" and further output has no
+ * effect. You must call glk_window_move_cursor() or glk_window_clear() to move
+ * the cursor back into the visible region.
+ *
+ * <note><para>
+ * Note that the arguments of glk_window_move_cursor() are <type>unsigned
+ * int</type>s. This is okay, since there are no negative positions. If you try
+ * to pass a negative value, Glk will interpret it as a huge positive value,
+ * and it will wrap or go off the last line.
+ * </para></note>
+ *
+ * <note><para>
+ * Also note that the output cursor is not necessarily visible. In particular,
+ * when you are requesting line or character input in a grid window, you cannot
+ * rely on the cursor position to prompt the player where input is indicated.
+ * You should print some character prompt at that spot -- a ">" character, for
+ * example.
+ * </para></note>
+ */
+void
+glk_window_move_cursor(winid_t win, glui32 xpos, glui32 ypos)