private void PerformSplit(int lines) { if (lines > 0) { if (upperWin.IsNull) { upperWin = Glk.glk_window_open(lowerWin, WinMethod.Above | WinMethod.Fixed, (uint)lines, WinType.TextGrid, 0); } else { Glk.glk_window_set_arrangement(Glk.glk_window_get_parent(upperWin), WinMethod.Above | WinMethod.Fixed, (uint)lines, winid_t.Null); } } else { if (!upperWin.IsNull) { stream_result_t dummy; Glk.glk_window_close(upperWin, out dummy); upperWin = winid_t.Null; currentWin = lowerWin; } } }
void IZMachineIO.SelectWindow(short num) { if (num == 0) { currentWin = lowerWin; } else if (num == 1) { /* work around a bug in some Inform games where the screen is erased, * destroying the split, but the split isn't restored before drawing * the status line. */ if (upperWin.IsNull) { ((IZMachineIO)this).SplitWindow(1); } currentWin = upperWin; } Glk.glk_set_window(currentWin); }
void IZMachineIO.EraseWindow(short num) { switch (num) { case 0: // lower only Glk.glk_window_clear(lowerWin); break; case 1: // upper only if (!upperWin.IsNull) { Glk.glk_window_clear(upperWin); } break; case -1: // erase both and unsplit if (!upperWin.IsNull) { stream_result_t dummy; Glk.glk_window_close(upperWin, out dummy); upperWin = winid_t.Null; } goto case -2; case -2: // erase both but keep split if (!upperWin.IsNull) { Glk.glk_window_clear(upperWin); } Glk.glk_window_clear(lowerWin); currentWin = lowerWin; xpos = 0; ypos = 0; break; } }
public static extern void glk_window_move_cursor(winid_t win, uint xpos, uint ypos);
public static extern void glk_cancel_mouse_event(winid_t win);
public static extern void glk_cancel_line_event(winid_t win, out event_t @event);
public static extern void glk_request_char_event_uni(winid_t win);
public static extern bool glk_style_measure(winid_t win, Style styl, StyleHint hint, out int result);
public static extern void glk_set_window(winid_t win);
public static extern void glk_window_get_arrangement(winid_t win, out WinMethod method, out uint sizeptr, out winid_t keywinptr);
public static extern void glk_window_set_arrangement(winid_t win, WinMethod method, uint size, winid_t keywin);
public static extern void glk_window_get_size(winid_t win, out uint width, out uint height);
public static extern void glk_window_close(winid_t win, out stream_result_t result);
public static extern winid_t glk_window_open(winid_t split, WinMethod method, uint size, WinType wintype, uint rock);
public static extern void glk_window_set_echo_stream(winid_t win, strid_t str);
public static extern winid_t glk_window_iterate(winid_t win, out uint rockptr);
public static extern strid_t glk_window_get_echo_stream(winid_t win);
public static extern uint glk_window_get_rock(winid_t win);
public static extern bool glk_style_distinguish(winid_t win, Style styl1, Style styl2);
public static extern WinType glk_window_get_type(winid_t win);
public static extern void glk_request_line_event_uni(winid_t win, IntPtr buf, uint maxlen, uint initlen);
public static extern winid_t glk_window_get_parent(winid_t win);
public static extern void glk_request_mouse_event(winid_t win);
public static extern winid_t glk_window_get_sibling(winid_t win);
public static extern void glk_cancel_char_event(winid_t win);
public static extern void glk_window_clear(winid_t win);
public static extern void garglk_set_line_terminators(winid_t win, [In] KeyCode[] keycodes, uint numkeycodes);
public GlkIO(string[] args, string storyName) { // initialize Glk // first, add the application's path to the beginning of the arg list string[] newArgs = new string[args.Length + 1]; newArgs[0] = Application.ExecutablePath; Array.Copy(args, 0, newArgs, 1, args.Length); args = newArgs; // now, GarGlk keeps pointers into argv, so we have to copy the args into unmanaged memory argv = Marshal.AllocHGlobal(4 * (args.Length + 1)); argvStrings = new IntPtr[args.Length]; for (int i = 0; i < args.Length; i++) { IntPtr str = Marshal.StringToHGlobalAnsi(args[i]); argvStrings[i] = str; Marshal.WriteIntPtr(argv, 4 * i, str); } Marshal.WriteIntPtr(argv, 4 * args.Length, IntPtr.Zero); Glk.gli_startup(args.Length, argv); Glk.garglk_set_program_name("Demona"); Glk.garglk_set_program_info("Demona by Jesse McGrew\nA Glk interface for ZLR\nVersion " + ZMachine.ZLR_VERSION); Glk.garglk_set_story_name(storyName); // set style hints Glk.glk_stylehint_set(WinType.AllTypes, Style.User1, StyleHint.ReverseColor, 1); Glk.glk_stylehint_set(WinType.AllTypes, Style.User2, StyleHint.Weight, 1); Glk.glk_stylehint_set(WinType.AllTypes, Style.User2, StyleHint.Proportional, 0); // figure out how big the screen is winid_t tempWin = Glk.glk_window_open(winid_t.Null, 0, 0, WinType.TextGrid, 0); if (tempWin.IsNull) { screenWidth = 80; screenHeight = 25; } else { Glk.glk_window_get_size(tempWin, out screenWidth, out screenHeight); stream_result_t dummy; Glk.glk_window_close(tempWin, out dummy); } // open the lower window lowerWin = Glk.glk_window_open(winid_t.Null, 0, 0, WinType.TextBuffer, 0); if (lowerWin.IsNull) { throw new Exception("glk_window_open failed"); } Glk.glk_set_window(lowerWin); currentWin = lowerWin; xpos = 0; ypos = 0; unicode = (Glk.glk_gestalt(Gestalt.Unicode, 0) != 0); }