Beispiel #1
0
        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);
            }
        }