short IZMachineIO.ReadKey(int time, TimedInputCallback callback, CharTranslator translator) { PerformSplit(targetSplit); if (unicode) { Glk.glk_request_char_event_uni(currentWin); } else { Glk.glk_request_char_event(currentWin); } Glk.glk_request_timer_events((uint)(time * 100)); event_t ev; bool done = false; short result = 0; do { Glk.glk_select(out ev); switch (ev.type) { case EvType.CharInput: if (ev.win == currentWin) { if (ev.val1 <= 255 || (unicode && ev.val1 <= 0x10000)) { result = translator((char)ev.val1); } else { result = GlkKeyToZSCII((KeyCode)ev.val1); } if (result != 0) { done = true; } else if (unicode) { Glk.glk_request_char_event_uni(currentWin); } else { Glk.glk_request_char_event(currentWin); } } break; case EvType.Timer: if (callback() == true) { Glk.glk_cancel_char_event(currentWin); done = true; } break; case EvType.Arrange: UpdateScreenSize(); break; case EvType.SoundNotify: SoundNotify(); break; } }while (!done); Glk.glk_request_timer_events(0); return(result); }
string IZMachineIO.ReadLine(string initial, int time, TimedInputCallback callback, byte[] terminatingKeys, out byte terminator) { const int BUFSIZE = 256; IntPtr buf = Marshal.AllocHGlobal(unicode ? BUFSIZE * 4 : BUFSIZE); Encoding encoding = unicode ? Encoding.UTF32 : Encoding.GetEncoding(Glk.LATIN1); try { uint initlen = 0; if (initial.Length > 0) { if (unicode) { Glk.garglk_unput_string_uni(initial); } else { Glk.garglk_unput_string(initial); } byte[] initBytes = encoding.GetBytes(initial); Marshal.Copy(initBytes, 0, buf, initBytes.Length); initlen = (uint)initBytes.Length; if (unicode) { initlen /= 4; } } if (unicode) { Glk.glk_request_line_event_uni(currentWin, buf, BUFSIZE, initlen); } else { Glk.glk_request_line_event(currentWin, buf, BUFSIZE, initlen); } Glk.glk_request_timer_events((uint)(time * 100)); KeyCode[] glkTerminators = null; if (terminatingKeys != null && terminatingKeys.Length > 0) { glkTerminators = GlkKeysFromZSCII(terminatingKeys); Glk.garglk_set_line_terminators(currentWin, glkTerminators, (uint)glkTerminators.Length); } terminator = 0; event_t ev; bool done = false; do { Glk.glk_select(out ev); switch (ev.type) { case EvType.LineInput: if (ev.win == currentWin) { done = true; if (glkTerminators == null || ev.val2 == 0) { terminator = 13; } else { terminator = GlkKeyToZSCII((KeyCode)ev.val2); } } break; case EvType.Timer: lineInputActive = true; if (callback() == true) { done = true; } else if (!lineInputActive) { // the callback cancelled the line input request to print something... if (unicode) { Glk.glk_request_line_event_uni(currentWin, buf, BUFSIZE, canceledLineEvent.val1); } else { Glk.glk_request_line_event(currentWin, buf, BUFSIZE, canceledLineEvent.val1); } if (glkTerminators != null) { Glk.garglk_set_line_terminators(currentWin, glkTerminators, (uint)glkTerminators.Length); } } break; case EvType.Arrange: UpdateScreenSize(); break; case EvType.SoundNotify: SoundNotify(); break; } }while (!done); Glk.glk_request_timer_events(0); PerformSplit(targetSplit); // convert the string from Latin-1 or UTF-32 int length = (int)ev.val1; if (unicode) { length *= 4; } byte[] bytes = new byte[length]; Marshal.Copy(buf, bytes, 0, length); return(encoding.GetString(bytes)); } finally { Marshal.FreeHGlobal(buf); } }