Hi all! 

 

I have found some TODO remarks in Console.cs :

/// TODO

      /// - typing in command

      ///         - move left/right in command

      ///         - insert overwrite

You can find changed files in attachment.

I have added new method to StringBuilder called Insert  and made some
changes in Console.cs

 

It works fine in VPC, but there is an issue with QEMU. Then you press any
arrow key or home\insert\pgup\pgdown keys there are strange characters
printed, but keys do their actions.  I have a feeling that after arrow key
code QEMU sends another code.. and I don't know why..  any ideas?

 

--

Best Regards,

Andrey Mezheninov

//
// (C) 2007 The SharpOS Project Team (http://www.sharpos.org)
//
// Authors:
//      William Lahti <[EMAIL PROTECTED]>
//      Bruce Markham <[EMAIL PROTECTED]>
//
// Licensed under the terms of the GNU GPL v3,
//  with Classpath Linking Exception for Libraries
//

using System;

using SharpOS.Kernel.Memory;
using SharpOS.Kernel.ADC;

namespace SharpOS.Kernel.Foundation {
        public unsafe struct StringBuilder {
                internal CString8* buffer;
                private uint capacity;
                private uint caret;

                public const uint DefaultCapacity = 127;

        private void Write_INTERNAL(byte* ptr, uint count)
                {
                        byte* oPtr = buffer->Pointer;
                        uint caretAdvance = count;
                        for (int x = 0; x < count; x++) {
                                if (ptr [x] == (byte) '\0') {
                                        caretAdvance = (uint) x + 1;
                                        break;
                                }
                                oPtr [caret + x] = ptr [x];
                        }
                        caret += caretAdvance;

                        Tie ();
                }
                private void Write_INTERNAL (string str)
                {
                        byte* oPtr = buffer->Pointer;
                        for (int x = 0; x < str.Length; x++) {
                                oPtr [caret + x] = (byte) str [x];
                        }
                        caret += (uint) str.Length;

                        Tie ();
                }
                private void Write_INTERNAL (byte ch)
                {
                        buffer->Pointer [caret] = ch;
                        caret = caret + 1;

                        Tie ();
                }

                public void AppendChar (byte ch)
                {
                        uint thisLength = (uint) this.Length;
                        EnsureCapacity (thisLength + 1);

                        Write_INTERNAL (ch);
                }

                public void AppendSubstring (byte* message, int offset, int len)
                {
                        for (int i = offset; message[i] != 0 && i < (offset + 
len); ++i)
                                Write_INTERNAL(message[i]);
                }

                public void Append (string str)
                {
                        uint strLength = (uint) str.Length;
                        uint thisLength = (uint) this.Length;
                        EnsureCapacity (thisLength + strLength);

                        Write_INTERNAL (str);
                }

                public void Append (byte* str)
                {
                        uint strLength = (uint) ByteString.Length (str);
                        uint thisLength = (uint) this.Length;
                        EnsureCapacity (strLength + thisLength);

                        Write_INTERNAL (str, strLength);
                }

        /// <summary>
        /// Inserts char to string builder.
        /// </summary>
        /// <remarks>
        /// Author:Crill
        /// </remarks>
        /// <param name="chr">Character to insert</param>
        /// <param name="position">zero based possition</param>
        public void Insert(byte chr, int position)
        {
            CString8* tail = buffer->Substring(position);
            buffer->SetChar(position, chr);
            caret = (uint)position + 1;
            EnsureCapacity((uint)Length+1);
            for (int i = 0; i < tail->Length; i++)
            {
                Write_INTERNAL(tail->GetChar(i));
            }
        }

        public void Append(CString8* str)
                {
                        Append ((byte*) str->Pointer);
                }

                public void AppendNumber (int number)
                {
                        AppendNumber (number, false);
                }

                public void AppendNumber (int number, bool hex)
                {
                        byte* str = (byte*) Convert.ToString (number, hex);
                        Append (str);
                        ADC.MemoryManager.Free ((void*) str);
                }

                public void AppendNumber (short number, bool hex)
                {
                        AppendNumber ((int) number, hex);
                }

                public void AppendNumber (short number)
                {
                        AppendNumber ((int) number, false);
                }

                public void AppendNumber (byte number, bool hex)
                {
                        AppendNumber ((int) number, hex);
                }

                public void Clear ()
                {
                        caret = 0;
                        Tie ();
                }

                private void Tie ()
                {
                        buffer->Pointer [caret] = (byte) '\0';
                }

                public int Length
                {
                        get
                        {
                                return this.buffer->Length;
                        }
                }

                public void RemoveAt (int startIndex, int count)
                {
                        if (count == 0)
                                return;

                        int length = this.Length;
                        Diagnostics.Assert (startIndex >= 0, 
"StringBuilder::Remove(int,int): Parameter 'startIndex' is out of range");
                        Diagnostics.Assert (startIndex < length, 
"StringBuilder::Remove(int,int): Parameter 'startIndex' is out of range");
                        Diagnostics.Assert (count >= 0, 
"StringBuilder::Remove(int,int): Parameter 'count' is out of range");
                        Diagnostics.Assert ((startIndex + count) <= length, 
"StringBuilder::Remove(int,int): Parameter 'count' is out of range");

                        int partA_last = startIndex - 1;

                        int partB_first = partA_last + count + 1;
                        int partB_last = this.Length - 1;
                        int partB_length = (partB_last - partB_first) + 1;

                        for (int x = 0; x < partB_length; x++) {
                                this.buffer->Pointer [partA_last + x + 1] =
                                    this.buffer->Pointer [partB_first + x];
                        }

                        caret = (uint) (partA_last + partB_length + 1);
                        Tie ();
                }

                private void Expand (uint amount)
                {
                        StringBuilder* tempInstance = CREATE (this.buffer, 
amount);
                        this.buffer = tempInstance->buffer;
                        this.capacity = tempInstance->capacity;
                        ADC.MemoryManager.Free (tempInstance);
                }

                public uint EnsureCapacity (uint minimumCapacity)
                {
                        if (minimumCapacity > this.capacity) {
                                uint amountToExpand =
                                    (((minimumCapacity - this.capacity) / 
DefaultCapacity) + 1)
                                        * DefaultCapacity;

                                this.Expand (amountToExpand);
                        }

                        return this.capacity;
                }

                public static StringBuilder* CREATE ()
                {
                        return CREATE (DefaultCapacity);
                }

                public static StringBuilder* CREATE (CString8* initialContents)
                {
                        Diagnostics.Assert (initialContents != null, 
"StringBuilder::Create(CString8*): Parameter 'initialContents' should not be 
null");
                        return CREATE (initialContents, DefaultCapacity);
                }

                public static StringBuilder* CREATE (uint initialCapacity)
                {
                        StringBuilder* instance = (StringBuilder*) 
ADC.MemoryManager.Allocate ((uint) sizeof (StringBuilder));

                        instance->buffer = (CString8*) 
ADC.MemoryManager.Allocate (initialCapacity + 1);
                        instance->capacity = initialCapacity;

                        byte* ptr = instance->buffer->Pointer;
                        for (int x = 0; x < (initialCapacity + 1); x++)
                                ptr [x] = (byte) '\0';

                        instance->caret = 0;

                        return instance;
                }

                public static StringBuilder* CREATE (CString8* initialContents, 
uint additionalPadding)
                {
                        Diagnostics.Assert (initialContents != null, 
"StringBuilder::Create(CString8*,uint): Parameter 'initialContents' should not 
be null");

                        StringBuilder* instance = (StringBuilder*) 
ADC.MemoryManager.Allocate ((uint) sizeof (StringBuilder));
                        uint initialCapacity = (uint) initialContents->Length + 
additionalPadding;

                        instance->buffer = (CString8*) 
ADC.MemoryManager.Allocate (initialCapacity + 1);
                        instance->capacity = initialCapacity;

                        byte* oPtr = instance->buffer->Pointer;
                        byte* iPtr = initialContents->Pointer;

                        bool inFill = false;
                        for (int x = 0; x < (instance->capacity); x++) {
                                if (!inFill && iPtr [x] == (byte) '\0')
                                        inFill = true;
                                if (inFill)
                                        oPtr [x] = (byte) '\0';
                                else {
                                        oPtr [x] = iPtr [x];
                                        instance->caret = (uint) x;
                                }
                        }
                        instance->caret = instance->caret + 1;
                        oPtr [instance->capacity + 1] = (byte) '\0';

                        return instance;
                }

                #region TESTS
                internal static void __RunTests ()
                {
                        __Test_Append ();
                        __Test_LengthAndCapacity ();
                        __Test_RemoveAt ();
                }

                private static void __Test_Append ()
                {
                        StringBuilder* sb = StringBuilder.CREATE (5);

                        sb->AppendChar ((byte) 'a');
                        Testcase.Test (sb->buffer->Pointer [0] == (byte) 'a',
                                "StringBuilder.AppendChar(byte)",
                                "Test A (append 'a')");

                        sb->Append ("b");
                        Testcase.Test (sb->buffer->Pointer [1] == (byte) 'b',
                                "StringBuilder.Append(string)",
                                "Test B (append 'b')");

                        ADC.MemoryManager.Free ((void*) sb);
                }

                private static void __Test_LengthAndCapacity ()
                {
                        StringBuilder* sb = StringBuilder.CREATE (50);
                        sb->Append ("abcd");
                        sb->Append ("e");

                        Testcase.Test (sb->Length == 5,
                                "StringBuilder.Append(string)",
                                "Length misalignment");
                        Testcase.Test (sb->capacity == 50,
                                "StringBuilder.Append(string)",
                                "Capacity misalignment");

                        sb->Clear ();
                        Testcase.Test (sb->Length == 0,
                                "StringBuilder.Clear()",
                                "Correct clear behavior");

                        ADC.MemoryManager.Free ((void*) sb);
                }

                private static void __Test_RemoveAt ()
                {
                        StringBuilder* sb = StringBuilder.CREATE (25);
                        sb->Append ("abcd");

                        sb->RemoveAt (1, 2);
                        Testcase.Test (sb->buffer->Compare ("ad") == 0,
                                "StringBuilder.RemoveAt(int,int)",
                                "Middle-of-string removal");

                        sb->Append ("e");
                        sb->RemoveAt (0, 2);
                        Testcase.Test (sb->buffer->Compare ("e") == 0,
                                "StringBuilder.RemoveAt(int,int)",
                                "Beginning-of-string removal");

                        sb->Append ("fg");
                        sb->RemoveAt (1, 2);
                        Testcase.Test (sb->buffer->Compare ("e") == 0,
                                "StringBuilder.RemoveAt(int,int)",
                                "End-of-string removal");

                        ADC.MemoryManager.Free ((void*) sb);
                }

                #endregion
        }
}
//
// (C) 2006-2007 The SharpOS Project Team (http://www.sharpos.org)
//
// Authors:
//      Sander van Rossen <[EMAIL PROTECTED]>
//      William Lahti <[EMAIL PROTECTED]>
//      Bruce Markham <[EMAIL PROTECTED]>
//
// Licensed under the terms of the GNU GPL v3,
//  with Classpath Linking Exception for Libraries
//

#define FORBID_ARROW_KEYS

using System;
using SharpOS.Kernel;
using SharpOS.Kernel.ADC;
using SharpOS.Kernel.Foundation;
using SharpOS.Kernel.Shell;

namespace SharpOS.Kernel {
        /// <summary>
        /// Provides basic console services
        /// </summary>
        /// <todo>
        /// TODO
        /// - add capslock/numlock support
        ///             just like we're now passing a 'shifted' boolean value 
to translate,
        ///             should we also pass a 'numlock' boolean value to 
translate?
        ///             maybe this needs to be generalized somehow (eventually)?
        ///             what if a keyboard manifacturer has programmable 
keys/modes etc.?
        ///             capslock is also not exactly the same as shift, because 
shift+1 is not the same as capslock+1
        /// </todo>
        public unsafe class Console {
                public const string CONSOLE_KEY_UP_HANDLER = 
"CONSOLE_KEY_UP_HANDLER";
                public const string CONSOLE_KEY_DOWN_HANDLER = 
"CONSOLE_KEY_DOWN_HANDLER";
                public const string CONSOLE_TIMER_HANDLER = 
"CONSOLE_TIMER_HANDLER";

        /// <summary>
        /// crill: Lenght of promter string ("#OS> " = 5)
        /// </summary>
        private const int promterLenght = 5;

                private static bool initialized = false;
                private static bool overwrite = false;

                private static StringBuilder* textBuffer;

                public static void Setup ()
                {
                        textBuffer = StringBuilder.CREATE ((uint) 80);

                        Keyboard.RegisterKeyUpEvent (Stubs.GetFunctionPointer 
(CONSOLE_KEY_UP_HANDLER));
                        Keyboard.RegisterKeyDownEvent (Stubs.GetFunctionPointer 
(CONSOLE_KEY_DOWN_HANDLER));
                        SharpOS.Kernel.ADC.Timer.RegisterTimerEvent 
(Stubs.GetFunctionPointer (CONSOLE_TIMER_HANDLER));
            
                        initialized = true;
                        TextMode.RefreshCursor ();
                        SetOverwrite (overwrite);

                }

                public static unsafe void SetOverwrite (bool _overwrite)
                {
                        overwrite = _overwrite;

                        if (overwrite)
                                TextMode.SetCursorSize (0, 15);
                        else
                                TextMode.SetCursorSize (13, 15);
                }

                [SharpOS.AOT.Attributes.Label (CONSOLE_KEY_UP_HANDLER)]
                public static unsafe void KeyUp (uint scancode)
                {
                        if (!initialized)
                                return;
                }

                public static uint pos = 0;

                [SharpOS.AOT.Attributes.Label (CONSOLE_KEY_DOWN_HANDLER)]
                public static unsafe void KeyDown (uint scancode)
                {
                        if (!initialized)
                                return;

                        // actually not correct because capslock does not 
behave like shift on all characters...

                        bool shifted = (Keyboard.LeftShift () || 
Keyboard.RightShift ());

                        TextMode.SetAttributes (TextColor.Yellow, 
TextColor.Black);

            int x, y, width, height;
            TextMode.GetScreenSize(out width, out height);
            TextMode.GetCursor(out x, out y);

                        ADC.Keys key = (ADC.Keys) scancode;
                        // switch statement doesn't for all cases somehow..
            // Crill: switch statement works fine and faster. 
            // it's a little issue in QEMU with arrows.
            switch (key)
            {
                case Keys.Insert:
                    overwrite = !overwrite;
                    SetOverwrite(overwrite);
                    break;
                case Keys.Delete:
                    break;
                case Keys.PageUp:
                    TextMode.ScrollPage(-1);
                    break;
                case Keys.PageDown:
                    TextMode.ScrollPage(+1);
                    break;
                case Keys.Backspace:
                    if (Console.textBuffer != null
                        && textBuffer->Length <= 0)
                    {
                        //Beep??
                        break;
                    }
                    x--;
                    if (x < 0)
                    {
                        x = width - 1;
                        y--;
                        if (y < 0)
                        {
                            y = 0;
                            break;
                        }
                    }
                    TextMode.MoveTo(x, y);
                    TextMode.WriteChar((byte)' ');

                    textBuffer->RemoveAt(textBuffer->Length - 1, 1);

                    TextMode.MoveTo(x, y);
                    TextMode.RefreshCursor();
                    break;
                case Keys.LeftArrow:
                    x--;
                    if (x < promterLenght)
                        x = promterLenght;
                    TextMode.MoveTo(x, y);
                    TextMode.RefreshCursor();

                    break;
                case Keys.RightArrow:
                    x++;
                    int distance = textBuffer->Length + promterLenght;
                    if (x > distance)
                        x = distance;
                    TextMode.MoveTo(x, y);
                    TextMode.RefreshCursor();
                    break;
                case Keys.UpArrow:
//#if !FORBID_ARROW_KEYS
//                int x, y, width, height;

//                TextMode.GetScreenSize(out width, out height);
//                TextMode.GetCursor(out x, out y);
//                y = y - 1; if (y < 0) y = 0;
//                TextMode.MoveTo(x, y);
//                TextMode.RefreshCursor();
//#else
//                    //TODO: Beep?
//#endif
                    break;
                //}
                case Keys.DownArrow:
                    //else if (key == Keys.DownArrow) {
//#if !FORBID_ARROW_KEYS
//                int x, y, width, height;

//                TextMode.GetScreenSize(out width, out height);
//                TextMode.GetCursor(out x, out y);
//                y = y + 1; if (y >= height) y = height - 1;
//                TextMode.MoveTo(x, y);
//                TextMode.RefreshCursor();
//#else
//                    //TODO: Beep?
//#endif
                    break;
                case Keys.Enter:
                    TextMode.WriteLine();
                    TextMode.ClearToEndOfLine();
                    TextMode.RefreshCursor();
                    DispatchBuffer();
                    break;
                default:
                    // Code to fix keymap issue with caps.
                    bool upperCase = shifted;
                    if (
                        (scancode >= 0x10 && scancode <= 0x26) ||
                        (scancode == 0x1e || scancode == 0x1f) ||
                        (scancode >= 0x2c && scancode <= 0x2f) ||
                        (scancode >= 0x30 && scancode <= 0x32))
                        upperCase ^= Keyboard.CapsLock();

                    byte character = Keyboard.Translate(scancode, upperCase);
                    if (character == 0)
                    {
                        // just so that you can actually see that keyboard 
input works (& we simply don't know what character you just pressed)...
                        TextMode.WriteChar((byte)'?');
                        TextMode.Write((int)scancode);
                        TextMode.RefreshCursor();
                        textBuffer->AppendChar((byte)255);
                        break;
                    }

                    int read = TextMode.GetReadPosition();
                    int write = TextMode.GetWritePosition();
                    if (read != write)
                        TextMode.SetReadPos(write);

                    //calculating cursor offset
                    int curs_offset = x - promterLenght;

                    //putting char in buffer
                    if (curs_offset >= textBuffer->Length || curs_offset < 0)
                    {
                        textBuffer->AppendChar(character);
                    }
                    else
                    {
                        if (overwrite)
                        {
                            textBuffer->buffer->SetChar(curs_offset, character);
                        }
                        else
                        {
                            textBuffer->Insert(character, curs_offset);
                        }
                    }

                    //redraw buffer as it is
                    TextMode.SetCursor(promterLenght, y);
                    for (int i = 0; i < textBuffer->Length; i++)
                        TextMode.WriteChar(textBuffer->buffer->GetChar(i));
                    TextMode.SetCursor(x + 1, y);
                    TextMode.RefreshCursor();
                    break;
            }
                }

                private static void DispatchBuffer ()
                {
                        CString8* bufferCopy = CString8.Copy 
(textBuffer->buffer);
                        Diagnostics.Assert (bufferCopy != null, 
"Prompter::DispatchBuffer(): INSANITY CHECK: CString8.Copy(byte*) returned 
NULL");
                        Prompter.QueueLine (bufferCopy);
                        CString8.DISPOSE (bufferCopy);
                        textBuffer->Clear ();
                }

                [SharpOS.AOT.Attributes.Label (CONSOLE_TIMER_HANDLER)]
                public static unsafe void Timer (uint ticks)
                {
                        if (ticks % SharpOS.Kernel.ADC.Timer.GetFrequency () == 
0) {
                                int x, y;
                                TextMode.GetCursor (out x, out y);
                                TextMode.SaveAttributes ();
                                TextMode.MoveTo (0, 24);
                                TextMode.SetAttributes (TextColor.Yellow, 
TextColor.Red);
                                Clock.Write ();
                                TextMode.RestoreAttributes ();
                                TextMode.MoveTo (x, y);
                        }

                        Shell.Prompter.Pulse ();
                }
        }
}


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
SharpOS-Developers mailing list
SharpOS-Developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sharpos-developers

Reply via email to