singrdk/base/Applications/Tests/ConsoleDemo/ConsoleDemo.sg

386 lines
14 KiB
Plaintext

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: ChannelDemo.cs
//
// Note: Simple Singularity test program.
//
using System;
using System.Threading;
using Microsoft.Singularity.V1.Services;
using Microsoft.Singularity.Channels;
using Microsoft.Singularity.Directory;
using Microsoft.Singularity.Io;
using Microsoft.SingSharp;
using Microsoft.Singularity.Channels;
using Microsoft.Contracts;
using Microsoft.SingSharp.Reflection;
using Microsoft.Singularity.Applications;
using Microsoft.Singularity.Io;
using Microsoft.Singularity.Configuration;
[assembly: Transform(typeof(ApplicationResourceTransform))]
namespace Microsoft.Singularity.Applications.Tests {
[ConsoleCategory(DefaultAction=true)]
internal class Parameters {
[InputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
[OutputEndpoint("data")]
public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
reflective internal Parameters();
internal int AppMain() {
return ConsoleDemo.AppMain(this);
}
}
public class ConsoleDemo
{
private static ConsoleDeviceContract.Imp
OpenConsoleInternal(DirectoryServiceContract.Imp! nsImp,
[Claims] char[]! in ExHeap deviceName)
{
ConsoleDeviceContract.Exp! exp;
ConsoleDeviceContract.Imp! imp;
ConsoleDeviceContract.NewChannel(out imp, out exp);
nsImp.SendBind(deviceName, exp);
switch receive
{
case nsImp.AckBind():
return imp;
break;
case nsImp.NakBind(rejectImp, error):
delete rejectImp;
delete imp;
break;
case nsImp.ChannelClosed():
throw new Exception("Channel closed during Console bind.");
delete imp;
break;
case nsImp.NakBindReparse(path, rest, linked, backExp):
assert linked == true;
assert rest == null;
delete backExp;
delete imp;
return OpenConsoleInternal(nsImp, path);
break;
}
return null;
}
private static ConsoleDeviceContract.Imp OpenConsole(string! devName)
{
DirectoryServiceContract.Imp ns = DirectoryService.NewClientEndpoint();
ConsoleDeviceContract.Imp imp =
OpenConsoleInternal(ns, Bitter.FromString2(devName));
delete ns;
if (imp != null) {
switch receive
{
case imp.Success():
break;
case imp.ContractNotSupported():
throw new Exception("ConsoleOutput: ContractNotSupported");
break;
case imp.ChannelClosed():
throw new Exception("ConsoleOutput: ChannelClosed");
break;
}
}
return imp;
}
private static void ConsoleWrite(ConsoleDeviceContract.Imp! imp,
string! message)
{
char[]! in ExHeap m = Bitter.FromString2(message);
imp.SendWrite(m, 0, m.Length);
imp.RecvAckWrite(out m);
delete m;
}
private static void DrawLine(ConsoleDeviceContract.Imp! imp,
int x1, int y1, int x2, int y2,
char c)
{
int dx = x2 - x1;
int dy = y2 - y1;
if (dx == 0) {
if (dy == 0) {
imp.SendPutCharAt(c, x1, y1);
imp.RecvAckPutCharAt();
return;
}
dy = dy / Math.Abs(dy);
for (int y = y1; y != y2; y += dy) {
imp.SendPutCharAt(c, x1, y);
imp.RecvAckPutCharAt();
}
return;
}
else if (dy == 0) {
dx = dx / Math.Abs(dx);
for (int x = x1; x != x2; x += dx) {
imp.SendPutCharAt(c, x, y1);
imp.RecvAckPutCharAt();
}
return;
}
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
double scale = 0;
int end = 0;
if (dx > dy) {
scale = 1.0 / (double)dx;
end = dx;
}
else {
scale = 1.0 / (double)dy;
end = dy;
}
for (int i = 0; i < end; i++) {
double x = (x1 * i * scale) + (x2 * (end - i - 1) * scale);
double y = (y1 *i* scale) + (y2 * (end - i - 1) * scale);
imp.SendPutCharAt(c, (int)x, (int)y);
imp.RecvAckPutCharAt();
}
}
private static void BoxDemo(ConsoleDeviceContract.Imp! imp,
int columns, int rows)
{
int cc = columns / 2;
int cr = rows / 2;
int edge = Math.Min(cc, cr);
for (int i = 0 ; i < edge; i++) {
DrawLine(imp, cc - i, cr - i, cc - i, cr + i, '*');
DrawLine(imp, cc - i, cr + i, cc + i, cr + i, '*');
DrawLine(imp, cc + i, cr + i, cc + i, cr - i, '*');
DrawLine(imp, cc + i, cr - i, cc - i, cr - i, '*');
Thread.Sleep(TimeSpan.FromMilliseconds(20));
DrawLine(imp, cc - i, cr - i, cc - i, cr + i, ' ');
DrawLine(imp, cc - i, cr + i, cc + i, cr + i, ' ');
DrawLine(imp, cc + i, cr + i, cc + i, cr - i, ' ');
DrawLine(imp, cc + i, cr - i, cc - i, cr - i, ' ');
}
}
private static void SpinBoxDemo(ConsoleDeviceContract.Imp! imp,
int columns, int rows)
{
const int twoPiSteps = 16;
int cc = columns / 2;
int cr = rows / 2;
int r = 2 * Math.Min(cc, cr) / 3;
double tau = 2 * Math.PI / twoPiSteps;
for (int i = 0 ; i < 5 * twoPiSteps; i++) {
double theta = i * tau;
int x = (int)(r * Math.Sin(theta));
int y = (int)(r * Math.Cos(theta));
DrawLine(imp, cc + x, cr + y, cc + y, cr - x, 'O');
DrawLine(imp, cc + y, cr - x, cc - x, cr - y, 'O');
DrawLine(imp, cc - x, cr - y, cc - y, cr + x, 'O');
DrawLine(imp, cc - y, cr + x, cc + x, cr + y, 'O');
Thread.Sleep(TimeSpan.FromMilliseconds(20));
DrawLine(imp, cc + x, cr + y, cc + y, cr - x, ' ');
DrawLine(imp, cc + y, cr - x, cc - x, cr - y, ' ');
DrawLine(imp, cc - x, cr - y, cc - y, cr + x, ' ');
DrawLine(imp, cc - y, cr + x, cc + x, cr + y, ' ');
}
}
private static void AnnounceDemo(ConsoleDeviceContract.Imp! imp,
string! title)
{
Thread.Sleep(TimeSpan.FromSeconds(3));
imp.SendClear();
imp.RecvAckClear();
imp.SendSetCursorPosition(0, 1); // Avoid top line for thread state
imp.RecvAckSetCursorPosition();
char []! in ExHeap buffer = Bitter.FromString2(title);
imp.SendWrite(buffer, 0, title.Length);
imp.RecvAckWrite(out buffer);
delete buffer;
Thread.Sleep(TimeSpan.FromSeconds(1));
}
private static void RunDemo(ConsoleDeviceContract.Imp! imp)
{
// This is just a quick placeholder that shows
// we can write at arbitrary points on the screen.
AnnounceDemo(imp, "Text positioning demo (diagonal 2:1)");
int columns, rows;
imp.SendGetDisplayDimensions();
imp.RecvDisplayDimensions(out columns, out rows);
int oldColumn, oldRow;
imp.SendGetCursorPosition();
imp.RecvCursorPosition(out oldColumn, out oldRow);
char []! in ExHeap message = Bitter.FromString2("Hello World");
for (int i = 2; i < 11; i++) {
imp.SendSetCursorPosition(2 * i, i);
imp.RecvAckSetCursorPosition();
imp.SendWrite(message, 0, message.Length);
imp.RecvAckWrite(out message);
}
Thread.Sleep(TimeSpan.FromMilliseconds(3000));
delete message;
// ---------------------------------------------------------------
AnnounceDemo(imp, "Testing PutCharAt(). Cursor here...");
for (int i = 0; i < columns; i++) {
imp.SendPutCharAt('#', i, 0);
imp.RecvAckPutCharAt();
imp.SendPutCharAt('#', i, rows - 1);
imp.RecvAckPutCharAt();
Thread.Sleep(TimeSpan.FromMilliseconds(10));
}
for (int i = 0; i < rows; i++) {
imp.SendPutCharAt('#', 0, i);
imp.RecvAckPutCharAt();
imp.SendPutCharAt('#', columns - 1, i);
imp.RecvAckPutCharAt();
Thread.Sleep(TimeSpan.FromMilliseconds(10));
}
// ---------------------------------------------------------------
AnnounceDemo(imp, "Testing SetCursorSize(Large)...");
imp.SendSetCursorSize(CursorSize.Large);
switch receive {
case imp.AckSetCursorSize():
ConsoleWrite(imp, "okay");
break;
case imp.NotSupported():
ConsoleWrite(imp, "not supported");
break;
}
// ---------------------------------------------------------------
AnnounceDemo(imp, "Testing SetCursorSize(Small)...");
imp.SendSetCursorSize(CursorSize.Small);
switch receive {
case imp.AckSetCursorSize():
Console.Write("okay");
break;
case imp.NotSupported():
Console.Write("not supported");
break;
}
// ---------------------------------------------------------------
AnnounceDemo(imp, "Testing SetCursorPosition()/PutChar(). Cursor moving.");
imp.SendSetCursorPosition(columns / 2, rows / 2);
imp.RecvAckSetCursorPosition();
imp.SendCursorShow();
imp.RecvAckCursorShow();
for (int i = 0; i < columns; i++) {
imp.SendSetCursorPosition(i, rows / 2);
imp.RecvAckSetCursorPosition();
imp.SendPutChar('>');
imp.RecvAckPutChar();
Thread.Sleep(TimeSpan.FromMilliseconds(10));
}
for (int i = 0; i < columns; i++) {
imp.SendSetCursorPosition(columns - i - 1, rows / 2);
imp.RecvAckSetCursorPosition();
imp.SendPutChar('<');
imp.RecvAckPutChar();
Thread.Sleep(TimeSpan.FromMilliseconds(10));
}
// ---------------------------------------------------------------
AnnounceDemo(imp, "Testing ClearCursorToEndOfLine().");
for (int c = 0; c < columns; c++) {
for (int r = 0; r < 10; r++) {
imp.SendPutCharAt('A', c, r + 3);
imp.RecvAckPutCharAt();
}
}
for (int r = 0; r < 5; r++) {
imp.SendSetCursorPosition(columns - r - 1, r + 3);
imp.RecvAckSetCursorPosition();
imp.SendClearCursorToEndOfLine();
imp.RecvAckClearCursorToEndOfLine();
Thread.Sleep(TimeSpan.FromMilliseconds(1000));
}
for (int r = 5; r < 10; r++) {
imp.SendSetCursorPosition(columns - 10 + r, r + 3);
imp.RecvAckSetCursorPosition();
imp.SendClearCursorToEndOfLine();
imp.RecvAckClearCursorToEndOfLine();
Thread.Sleep(TimeSpan.FromMilliseconds(1000));
}
// ---------------------------------------------------------------
AnnounceDemo(imp, "Cursor is about to be hidden and boxes drawn.");
imp.SendCursorHide();
imp.RecvAckCursorHide();
BoxDemo(imp, columns, rows);
// ---------------------------------------------------------------
AnnounceDemo(imp, "Spinning Box demo.");
SpinBoxDemo(imp, columns, rows);
// ---------------------------------------------------------------
imp.SendCursorShow();
imp.RecvAckCursorShow();
imp.SendClear();
imp.RecvAckClear();
imp.SendSetCursorPosition(oldColumn, oldRow);
imp.RecvAckSetCursorPosition();
}
internal static int AppMain(Parameters! config)
{
foreach (string s in new string [] { "/dev/video-text",
"/dev/conout" }) {
ConsoleDeviceContract.Imp imp = OpenConsole((!)s);
if (imp != null) {
Console.WriteLine("Opened {0}\n", s);
RunDemo(imp);
delete imp;
break;
}
}
return 0;
}
}
}