Exemplo n.º 1
0
        public BufferCell[,] NewBufferCellArray(int width, int height, BufferCell contents)
        {
            if (width <= 0)
            {
                throw PSTraceSource.NewArgumentOutOfRangeException("width", width, "MshHostRawUserInterfaceStrings", "NonPositiveNumberErrorTemplate", new object[] { "width" });
            }
            if (height <= 0)
            {
                throw PSTraceSource.NewArgumentOutOfRangeException("height", height, "MshHostRawUserInterfaceStrings", "NonPositiveNumberErrorTemplate", new object[] { "height" });
            }
            BufferCell[,] cellArray = new BufferCell[height, width];
            switch (this.LengthInBufferCells(contents.Character))
            {
            case 1:
                for (int i = 0; i < cellArray.GetLength(0); i++)
                {
                    for (int j = 0; j < cellArray.GetLength(1); j++)
                    {
                        cellArray[i, j] = contents;
                        cellArray[i, j].BufferCellType = BufferCellType.Complete;
                    }
                }
                return(cellArray);

            case 2:
            {
                int num4 = ((width % 2) == 0) ? width : (width - 1);
                for (int k = 0; k < height; k++)
                {
                    for (int m = 0; m < num4; m++)
                    {
                        cellArray[k, m] = contents;
                        cellArray[k, m].BufferCellType = BufferCellType.Leading;
                        m++;
                        cellArray[k, m] = new BufferCell('\0', contents.ForegroundColor, contents.BackgroundColor, BufferCellType.Trailing);
                    }
                    if (num4 < width)
                    {
                        cellArray[k, num4] = contents;
                        cellArray[k, num4].BufferCellType = BufferCellType.Leading;
                    }
                }
                break;
            }
            }
            return(cellArray);
        }
Exemplo n.º 2
0
        public BufferCell[,] NewBufferCellArray(int width, int height, BufferCell contents)
        {
            if (width <= 0)
            {
                throw PSTraceSource.NewArgumentOutOfRangeException("width", width, "MshHostRawUserInterfaceStrings", "NonPositiveNumberErrorTemplate", new object[] { "width" });
            }
            if (height <= 0)
            {
                throw PSTraceSource.NewArgumentOutOfRangeException("height", height, "MshHostRawUserInterfaceStrings", "NonPositiveNumberErrorTemplate", new object[] { "height" });
            }
            BufferCell[,] cellArray = new BufferCell[height, width];
            switch (this.LengthInBufferCells(contents.Character))
            {
                case 1:
                    for (int i = 0; i < cellArray.GetLength(0); i++)
                    {
                        for (int j = 0; j < cellArray.GetLength(1); j++)
                        {
                            cellArray[i, j] = contents;
                            cellArray[i, j].BufferCellType = BufferCellType.Complete;
                        }
                    }
                    return cellArray;

                case 2:
                {
                    int num4 = ((width % 2) == 0) ? width : (width - 1);
                    for (int k = 0; k < height; k++)
                    {
                        for (int m = 0; m < num4; m++)
                        {
                            cellArray[k, m] = contents;
                            cellArray[k, m].BufferCellType = BufferCellType.Leading;
                            m++;
                            cellArray[k, m] = new BufferCell('\0', contents.ForegroundColor, contents.BackgroundColor, BufferCellType.Trailing);
                        }
                        if (num4 < width)
                        {
                            cellArray[k, num4] = contents;
                            cellArray[k, num4].BufferCellType = BufferCellType.Leading;
                        }
                    }
                    break;
                }
            }
            return cellArray;
        }
Exemplo n.º 3
0
        private static void WriteConsoleOutputPlain(ConsoleHandle consoleHandle, Coordinates origin, BufferCell[,] contents)
        {
            int rows = contents.GetLength(0);
            int cols = contents.GetLength(1);

            if ((rows <= 0) || cols <= 0)
            {
                tracer.WriteLine("contents passed in has 0 rows and columns");
                return;
            }
            int bufferLimit = 2 * 1024; // Limit is 8K bytes as each CHAR_INFO takes 4 bytes

            COORD bufferCoord;

            bufferCoord.X = 0;
            bufferCoord.Y = 0;

            // keeps track of which screen area write
            SMALL_RECT writeRegion;

            writeRegion.Top = (short)origin.Y;

            int rowsRemaining = rows;

            while (rowsRemaining > 0)
            {
                // Iteration of columns is nested inside iteration of rows.
                // If the size of contents exceeds the buffer limit, writing is
                // done in blocks of size equal to the bufferlimit from left to right
                // then top to bottom.
                // For each iteration of rows,
                // - writeRegion.Left and bufferSize.X are reset
                // - rowsRemaining, writeRegion.Top, writeRegion.Bottom, and bufferSize.Y
                //     are updated
                //   For each iteration of columns,
                //   - writeRegion.Left, writeRegion.Right and bufferSize.X are updated

                writeRegion.Left = (short)origin.X;

                COORD bufferSize;

                bufferSize.X = (short)Math.Min(cols, bufferLimit);
                bufferSize.Y = (short)Math.Min
                                        (
                                            rowsRemaining,
                                            bufferLimit / bufferSize.X
                                        );
                writeRegion.Bottom = (short)(writeRegion.Top + bufferSize.Y - 1);

                // atRow is at which row of contents a particular iteration is operating
                int atRow = rows - rowsRemaining + contents.GetLowerBound(0);

                // number of columns yet to be written
                int colsRemaining = cols;

                while (colsRemaining > 0)
                {
                    writeRegion.Right = (short)(writeRegion.Left + bufferSize.X - 1);

                    // atCol is at which column of contents a particular iteration is operating
                    int atCol = cols - colsRemaining + contents.GetLowerBound(1);
                    CHAR_INFO[] characterBuffer = new CHAR_INFO[bufferSize.Y * bufferSize.X];

                    // copy characterBuffer to contents;
                    for (int r = atRow, characterBufferIndex = 0;
                        r < bufferSize.Y + atRow; r++)
                    {
                        for (int c = atCol; c < bufferSize.X + atCol; c++, characterBufferIndex++)
                        {
                            characterBuffer[characterBufferIndex].UnicodeChar =
                                (ushort)contents[r, c].Character;
                            characterBuffer[characterBufferIndex].Attributes =
                                ColorToWORD(contents[r, c].ForegroundColor, contents[r, c].BackgroundColor);
                        }
                    }

                    // Now writeRegion, bufferSize and characterBuffer are updated.
                    // Call NativeMethods.WriteConsoleOutput
                    bool result =
                        NativeMethods.WriteConsoleOutput(
                            consoleHandle.DangerousGetHandle(),
                            characterBuffer,
                            bufferSize,
                            bufferCoord,
                            ref writeRegion);

                    if (result == false)
                    {
                        // When WriteConsoleOutput fails, half bufferLimit
                        if (bufferLimit < 2)
                        {
                            int err = Marshal.GetLastWin32Error();
                            HostException e = CreateHostException(err, "WriteConsoleOutput",
                                ErrorCategory.WriteError, ConsoleControlStrings.WriteConsoleOutputExceptionTemplate);
                            throw e;
                        }
                        bufferLimit /= 2;
                        if (cols == colsRemaining)
                        {
                            // if cols == colsRemaining, nothing is guaranteed written in this pass and
                            //  the unwritten area is still rectangular
                            bufferSize.Y = 0;
                            break;
                        }
                        else
                        {
                            // some areas have been written. This could only happen when the number of columns
                            // to write is larger than bufferLimit. In that case, the algorithm writes one row
                            // at a time => bufferSize.Y == 1. Then, we can safely leave bufferSize.Y unchanged
                            // to retry with a smaller bufferSize.X.
                            Dbg.Assert(bufferSize.Y == 1, string.Format(CultureInfo.InvariantCulture, "bufferSize.Y should be 1, but is {0}", bufferSize.Y));
                            bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                            continue;
                        }
                    }

                    colsRemaining -= bufferSize.X;
                    writeRegion.Left += bufferSize.X;
                    bufferSize.X = (short)Math.Min(colsRemaining, bufferLimit);
                }  // column iteration

                rowsRemaining -= bufferSize.Y;
                writeRegion.Top += bufferSize.Y;
            }  // row iteration
        }
Exemplo n.º 4
0
        /// <summary>
        /// Wrap32 WriteConsoleOutput.
        /// This wrapper is not limited to 64K or 8K CHAR_INFO to which Win32's WriteConsoleOutput
        /// is constrained.
        /// </summary>
        /// <param name="consoleHandle">
        /// 
        /// handle for the console where output is written
        /// 
        /// </param>
        /// <param name="origin">
        /// 
        /// location on screen buffer where writing starts
        /// 
        /// </param>
        /// <param name="contents">
        /// 
        /// 2D array of cells. Caller needs to ensure that the array is 2D.
        /// 
        /// </param>
        /// <exception cref="HostException">
        /// If Win32's GetConsoleScreenBufferInfo fails
        /// If there is not enough memory to complete calls to Win32's WriteConsoleOutput
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// If <paramref name="contents"/> is null
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If it is illegal to write <paramref name="contents"/> to the output buffer 
        /// </exception>

        internal static void WriteConsoleOutput(ConsoleHandle consoleHandle, Coordinates origin, BufferCell[,] contents)
        {
            Dbg.Assert(!consoleHandle.IsInvalid, "ConsoleHandle is not valid");
            Dbg.Assert(!consoleHandle.IsClosed, "ConsoleHandle is closed");
            if (contents == null)
            {
                throw PSTraceSource.NewArgumentNullException("contents");
            }
            uint codePage;
            if (IsCJKOutputCodePage(out codePage))
            {
                // contentsRegion indicates the area in contents (declared below) in which
                // the data read from ReadConsoleOutput is stored.
                Rectangle contentsRegion = new Rectangle();
                ConsoleControl.CONSOLE_SCREEN_BUFFER_INFO bufferInfo =
                    GetConsoleScreenBufferInfo(consoleHandle);

                int bufferWidth = bufferInfo.BufferSize.X;
                int bufferHeight = bufferInfo.BufferSize.Y;
                Rectangle screenRegion = new Rectangle(
                    origin.X, origin.Y,
                    Math.Min(origin.X + contents.GetLength(1) - 1, bufferWidth - 1),
                    Math.Min(origin.Y + contents.GetLength(0) - 1, bufferHeight - 1));

                contentsRegion.Left = contents.GetLowerBound(1);
                contentsRegion.Top = contents.GetLowerBound(0);
                contentsRegion.Right = contentsRegion.Left +
                    screenRegion.Right - screenRegion.Left;
                contentsRegion.Bottom = contentsRegion.Top +
                    screenRegion.Bottom - screenRegion.Top;

#if DEBUG
                //Check contents in contentsRegion
                CheckWriteConsoleOutputContents(contents, contentsRegion);
#endif

                //Identify edges and areas of identical contiguous edges in contentsRegion
                List<BufferCellArrayRowTypeRange> sameEdgeAreas = new List<BufferCellArrayRowTypeRange>();
                int firstLeftTrailingRow = -1, firstRightLeadingRow = -1;
                BuildEdgeTypeInfo(contentsRegion, contents,
                    sameEdgeAreas, out firstLeftTrailingRow, out firstRightLeadingRow);

#if DEBUG
                CheckWriteEdges(consoleHandle, codePage, origin, contents, contentsRegion,
                    bufferInfo, firstLeftTrailingRow, firstRightLeadingRow);
#endif

                foreach (BufferCellArrayRowTypeRange area in sameEdgeAreas)
                {
                    Coordinates o = new Coordinates(origin.X,
                                                    origin.Y + area.Start - contentsRegion.Top);
                    Rectangle contRegion = new Rectangle(
                        contentsRegion.Left, area.Start, contentsRegion.Right, area.End);
                    if ((area.Type & BufferCellArrayRowType.LeftTrailing) != 0)
                    {
                        contRegion.Left++;
                        o.X++;
                        if (o.X >= bufferWidth || contRegion.Right < contRegion.Left)
                        {
                            return;
                        }
                    }

                    WriteConsoleOutputCJK(consoleHandle, o, contRegion, contents, area.Type);
                }
            }
            else
            {
                WriteConsoleOutputPlain(consoleHandle, origin, contents);
            }
        }
Exemplo n.º 5
0
        public void SetBufferContents(Coordinates origin, BufferCell[,] contents)
        {
            TextPointer lineStart, lineEnd, cell, rowEnd, originCell;
            TextRange row;
            Run r;
            Brush back, fore;
            BufferCell bc;

            int lines = 0, x = 0, y = 0, diff;
            int height = contents.GetLength(0);
            int width = contents.GetLength(1);

            lineStart = CaretPosition.DocumentStart.GetInsertionPosition(LogicalDirection.Forward).GetLineStartPosition(origin.Y, out lines);
            while (lines < origin.Y)
            {
                for (; lines < origin.Y; lines++)
                {
                    CaretPosition.DocumentEnd.InsertLineBreak();
                }
                lineStart = CaretPosition.DocumentStart.GetInsertionPosition(LogicalDirection.Forward).GetLineStartPosition(origin.Y, out lines);
            }

            if (origin.X > 0)
            {
                cell = originCell = lineStart.GetPositionAtOffset(origin.X).GetInsertionPosition(LogicalDirection.Forward);
            }
            else
            {
                cell = originCell = lineStart.GetInsertionPosition(LogicalDirection.Forward);
            }
            lineStart = originCell.GetLineStartPosition(1, out lines);
            lineEnd = lineStart.GetNextInsertionPosition(LogicalDirection.Backward);

            if (lines != 1)
            {
                lineStart.Paragraph.ElementEnd.InsertLineBreak();
            }
            BeginChange();
            while (y < height)
            {
                diff = 0;
                rowEnd = cell.GetPositionAtOffset(width);
                #region clear existing text
                if (null != rowEnd && null != lineEnd)
                {
                    diff = rowEnd.GetOffsetToPosition(lineEnd);
                }

                if (diff > 0 || lineEnd == null)
                {
                    row = new TextRange(cell, rowEnd);
                }
                else
                {
                    row = new TextRange(cell, lineStart);
                }
                row.Text = String.Empty;
                #endregion clear existing text

                // insert new text
                r = new Run(String.Empty, row.Start);

                r.Background = Background;
                r.Foreground = Foreground;
                for (x = 0; x < width; ++x)
                {
                    bc = contents[y, x];
                    back = BrushFromConsoleColor(bc.BackgroundColor);
                    fore = BrushFromConsoleColor(bc.ForegroundColor);

                    if (r.Background != back || r.Foreground != fore)
                    {
                        r = new Run(bc.Character.ToString(), r.ElementEnd);
                        r.Background = back;
                        r.Foreground = fore;
                    }
                    else
                    {
                        r.Text += bc.Character;
                    }
                }
                if (diff <= 0 && lineEnd != null)
                {
                    row.End.InsertLineBreak();
                    lineStart = row.Start.GetLineStartPosition(1);
                }

                // try advancing one line ...
                if (origin.X > 0)
                {
                    cell = lineStart.GetPositionAtOffset(origin.X).GetInsertionPosition(LogicalDirection.Forward);
                }
                else
                {
                    cell = lineStart.GetInsertionPosition(LogicalDirection.Forward);
                }
                lineStart = lineStart.GetLineStartPosition(1, out lines);
                if (lines != 1)
                {
                    lineStart.InsertLineBreak();
                    lineStart = lineStart.GetLineStartPosition(1, out lines);
                }
                lineEnd = lineStart.GetNextInsertionPosition(LogicalDirection.Backward);

                y++;
                x = 0;
            }
            EndChange();
        }
Exemplo n.º 6
0
        /// <summary>
        /// This method copies an array of buffer cells into the screen buffer
        /// at a specified location.
        /// </summary>
        /// <param name="origin">The parameter used to set the origin where the buffer where begin writing to.</param>
        /// <param name="contents">The parameter used to contain the contents to be written to the buffer.</param>
        public override void SetBufferContents(Coordinates origin,
                                               BufferCell[,] contents)
        {
            //if there are no contents, there is nothing to set the buffer to
            if (contents == null)
            {
                PSTraceSource.NewArgumentNullException("contents");
            }

            //if the cursor is on the last line, we need to make more space to print the specified buffer
            if (origin.Y == BufferSize.Height - 1 && origin.X >= BufferSize.Width)
            {
                //for each row in the buffer, create a new line
                int rows = contents.GetLength(0);
                ScrollBuffer(rows);
                // for each row in the buffer, move the cursor y up to the beginning of the created blank space
                // but not above zero
                if (origin.Y >= rows)
                {
                    origin.Y -= rows;
                }
            }

            //iterate through the buffer to set
            foreach (var charitem in contents)
            {
                //set the cursor to false to prevent cursor flicker
                Console.CursorVisible = false;

                //if x is exceeding buffer width, reset to the next line
                if (origin.X >= BufferSize.Width)
                {
                    origin.X = 1;
                }

                //write the character from contents
                Console.Out.Write(charitem.Character);

                //advance the character one position
                origin.X++;
            }

            //reset the cursor to the original position
            CursorPosition = origin;
            //reset the cursor to visible
            Console.CursorVisible = true;
        }
Exemplo n.º 7
0
        NewBufferCellArray(int width, int height, BufferCell contents)
        {
            if (width <= 0)
            {
                // "width" is not localizable
                throw PSTraceSource.NewArgumentOutOfRangeException("width", width,
                    MshHostRawUserInterfaceStrings.NonPositiveNumberErrorTemplate, "width");
            }

            if (height <= 0)
            {
                // "height" is not localizable
                throw PSTraceSource.NewArgumentOutOfRangeException("height", height,
                    MshHostRawUserInterfaceStrings.NonPositiveNumberErrorTemplate, "height");
            }

            BufferCell[,] buffer = new BufferCell[height, width];
            int charLength = LengthInBufferCells(contents.Character);
            if (charLength == 1)
            {
                for (int r = 0; r < buffer.GetLength(0); ++r)
                {
                    for (int c = 0; c < buffer.GetLength(1); ++c)
                    {
                        buffer[r, c] = contents;
                        buffer[r, c].BufferCellType = BufferCellType.Complete;
                    }
                }
            }
            else if (charLength == 2)
            {
                int normalizedWidth = width % 2 == 0 ? width : width - 1;
                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < normalizedWidth; j++)
                    {
                        buffer[i, j] = contents;
                        buffer[i, j].BufferCellType = BufferCellType.Leading;
                        j++;
                        buffer[i, j] = new BufferCell((char)0,
                            contents.ForegroundColor, contents.BackgroundColor,
                            BufferCellType.Trailing);
                    }
                    if (normalizedWidth < width)
                    {
                        buffer[i, normalizedWidth] = contents;
                        buffer[i, normalizedWidth].BufferCellType = BufferCellType.Leading;
                    }
                }
            }
            return buffer;
        }
Exemplo n.º 8
0
		private static void WriteConsoleOutputPlain(SafeFileHandle consoleHandle, Coordinates origin, BufferCell[,] contents)
		{
			int length = contents.GetLength(0);
			int num = contents.GetLength(1);
			if (length <= 0 || num <= 0)
			{
				ConsoleControl.tracer.WriteLine("contents passed in has 0 rows and columns", new object[0]);
				return;
			}
			else
			{
				int num1 = 0x800;
				ConsoleControl.COORD cOORD;
                cOORD.X = 0;
				cOORD.Y = 0;
				ConsoleControl.SMALL_RECT y;
                y.Top = (short)origin.Y;
				int y1 = length;
				while (y1 > 0)
				{
					y.Left = (short)origin.X;
					ConsoleControl.COORD cOORD1;
                    cOORD1.X = (short)Math.Min(num, num1);
					cOORD1.Y = (short)Math.Min(y1, num1 / cOORD1.X);
					y.Bottom = (short)(y.Top + cOORD1.Y - 1);
					int lowerBound = length - y1 + contents.GetLowerBound(0);
					int x = num;
					while (x > 0)
					{
						y.Right = (short)(y.Left + cOORD1.X - 1);
						int lowerBound1 = num - x + contents.GetLowerBound(1);
						ConsoleControl.CHAR_INFO[] character = new ConsoleControl.CHAR_INFO[cOORD1.Y * cOORD1.X];
						int num2 = lowerBound;
						int num3 = 0;
						while (num2 < cOORD1.Y + lowerBound)
						{
							int num4 = lowerBound1;
							while (num4 < cOORD1.X + lowerBound1)
							{
								character[num3].UnicodeChar = contents[num2, num4].Character;
								character[num3].Attributes = ConsoleControl.ColorToWORD(contents[num2, num4].ForegroundColor, contents[num2, num4].BackgroundColor);
								num4++;
								num3++;
							}
							num2++;
						}
						bool flag = ConsoleControl.NativeMethods.WriteConsoleOutput(consoleHandle.DangerousGetHandle(), character, cOORD1, cOORD, ref y);
						if (flag)
						{
							x = x - cOORD1.X;
							y.Left = (short)(y.Left + cOORD1.X);
							cOORD1.X = (short)Math.Min(x, num1);
						}
						else
						{
							if (num1 >= 2)
							{
								num1 = num1 / 2;
								if (num != x)
								{
									cOORD1.X = (short)Math.Min(x, num1);
								}
								else
								{
									cOORD1.Y = 0;
									break;
								}
							}
							else
							{
								int lastWin32Error = Marshal.GetLastWin32Error();
								HostException hostException = ConsoleControl.CreateHostException(lastWin32Error, "WriteConsoleOutput", ErrorCategory.WriteError, ConsoleControlStrings.WriteConsoleOutputExceptionTemplate);
								throw hostException;
							}
						}
					}
					y1 = y1 - cOORD1.Y;
					y.Top = (short)(y.Top + cOORD1.Y);
				}
				return;
			}
		}
Exemplo n.º 9
0
		internal static void WriteConsoleOutput(SafeFileHandle consoleHandle, Coordinates origin, BufferCell[,] contents)
		{
			uint num = 0;
			if (contents != null)
			{
				if (!ConsoleControl.IsCJKOutputCodePage(out num))
				{
					ConsoleControl.WriteConsoleOutputPlain(consoleHandle, origin, contents);
				}
				else
				{
					Rectangle lowerBound = new Rectangle();
					ConsoleControl.CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo = ConsoleControl.GetConsoleScreenBufferInfo(consoleHandle);
					int x = consoleScreenBufferInfo.BufferSize.X;
					int y = consoleScreenBufferInfo.BufferSize.Y;
					Rectangle rectangle = new Rectangle(origin.X, origin.Y, Math.Min(origin.X + contents.GetLength(1) - 1, x - 1), Math.Min(origin.Y + contents.GetLength(0) - 1, y - 1));
					lowerBound.Left = contents.GetLowerBound(1);
					lowerBound.Top = contents.GetLowerBound(0);
					lowerBound.Right = lowerBound.Left + rectangle.Right - rectangle.Left;
					lowerBound.Bottom = lowerBound.Top + rectangle.Bottom - rectangle.Top;
					ConsoleControl.CheckWriteConsoleOutputContents(contents, lowerBound);
					List<ConsoleControl.BufferCellArrayRowTypeRange> bufferCellArrayRowTypeRanges = new List<ConsoleControl.BufferCellArrayRowTypeRange>();
					int num1 = -1;
					int num2 = -1;
					ConsoleControl.BuildEdgeTypeInfo(lowerBound, contents, bufferCellArrayRowTypeRanges, out num1, out num2);
					ConsoleControl.CheckWriteEdges(consoleHandle, num, origin, contents, lowerBound, consoleScreenBufferInfo, num1, num2);
					foreach (ConsoleControl.BufferCellArrayRowTypeRange bufferCellArrayRowTypeRange in bufferCellArrayRowTypeRanges)
					{
						Coordinates coordinate = new Coordinates(origin.X, origin.Y + bufferCellArrayRowTypeRange.Start - lowerBound.Top);
						Rectangle left = new Rectangle(lowerBound.Left, bufferCellArrayRowTypeRange.Start, lowerBound.Right, bufferCellArrayRowTypeRange.End);
						if ((bufferCellArrayRowTypeRange.Type & ConsoleControl.BufferCellArrayRowType.LeftTrailing) != 0)
						{
							left.Left = left.Left + 1;
							coordinate.X = coordinate.X + 1;
							if (coordinate.X >= x || left.Right < left.Left)
							{
								return;
							}
						}
						ConsoleControl.WriteConsoleOutputCJK(consoleHandle, coordinate, left, contents, bufferCellArrayRowTypeRange.Type);
					}
				}
				return;
			}
			else
			{
				throw PSTraceSource.NewArgumentNullException("contents");
			}
		}