📄 ascscrn.cpp
字号:
// AsciiScreen methods
//
// $Id: ascscrn.cpp 2.2 1996/02/04 22:31:39 tsurace Exp $
// $Log: ascscrn.cpp $// Revision 2.2 1996/02/04 22:31:39 tsurace// Added code to handle illegal cursor placement gracefully.//
// Revision 2.1 1995/10/24 15:52:51 tsurace
// Roll.
//
// Revision 1.5 1995/10/15 23:27:50 tsurace
// Added a comment.
//
// Revision 1.4 1995/10/11 20:58:37 tsurace
// Switched to my ASSERT macro.
// Fixed reverse-scroll bug that caused core (or ASSERT failure).
// Added try/catch blocks to stop memory leaks.
//
// Revision 1.3 1995/10/08 23:27:10 tsurace
// Added ansi (foreground) color support.
//
// (end of log)
#define STRICT
#include <windows.h>
#pragma hdrstop
#include <except.h> // xalloc
#include <string.h> // memset()
#include "ascscrn.hpp"
#include "debug.hpp"
// ANSI color definitions are given names here to make it easier to tweak
// individual colors by name instead of figuring where they are in the
// lookup table
#define _BLACK RGB(0,0,0)
#define _RED RGB(160,0,0)
#define _GREEN RGB(0,160,0)
#define _YELLOW RGB(160,160,0)
#define _BLUE RGB(0,0,160)
#define _MAGENTA RGB(160,0,160)
#define _CYAN RGB(0,160,160)
#define _WHITE RGB(192,192,192)
// These are used if the bold attribute is set
#define _LT_BLACK RGB(128,128,128)
#define _LT_RED RGB(255,0,0)
#define _LT_GREEN RGB(0,255,0)
#define _LT_YELLOW RGB(255,255,0)
#define _LT_BLUE RGB(0,0,255)
#define _LT_MAGENTA RGB(255,0,255)
#define _LT_CYAN RGB(0,255,255)
#define _LT_WHITE RGB(255,255,255)
// Non-bold colors lookup table
COLORREF _ansiColorLookup[2][8] = // 8 colors normal, 8 colors bold
{
{_BLACK, _RED, _GREEN, _YELLOW,
_BLUE, _MAGENTA, _CYAN, _WHITE},
{_LT_BLACK, _LT_RED, _LT_GREEN, _LT_YELLOW,
_LT_BLUE, _LT_MAGENTA, _LT_CYAN, _LT_WHITE},
};
// ------------------------------------------------------------------------
// _LookupAnsiColor - a silly function to find a function in the
// lookup array.
//
// Parameters:
// bold - 0 if not bold, 1 if bold
// color - 0-7 to get the respective ibm pc color thingy
//
static inline COLORREF _LookupAnsiColor(int bold, int color)
{
ASSERT(0 == bold || 1 == bold, "Bold can be either 0 or 1");
ASSERT(color >= 0 && color <= 7, "Color out of range");
return _ansiColorLookup[bold][color];
};
// Constructor - Allocates memory for a screen width X height
//
// Interesting parameters:
// f - function that is called when an area of the screen needs to be
// redrawn. May not be NULL
// copy_func - called to request a copy of one area of the screen to
// another. If this returns 1, the area is not invalidated, otherwise
// it is. May not be NULL
AsciiScreen::AsciiScreen(int width,
int height,
COLORREF foreground,
COLORREF boldForeground,
void (*f)(const Pos & pos,
const Size & size,
void * extra),
void * invalidateFuncExtra,
int (*scroll_func)(int, int, int, void *),
void * scrollFuncExtra)
: _cursor(0,0),
_normalForeground(foreground),
_cursorForeground(foreground),
_cursorIsBold(0),
_boldForeground(boldForeground),
_width(width),
_height(height),
_scrollRegionTop(0),
_scrollRegionBottom(height-1),
_text(new char[width * height]),
_invalidateFunc(f),
_invalidateFuncExtra(invalidateFuncExtra),
_scrollFunc(scroll_func),
_scrollFuncExtra(scrollFuncExtra),
_foreground(new COLORREF[width * height])
{
ASSERT(NULL != _invalidateFunc, "Bad function pointer");
ASSERT(NULL != _scrollFunc, "Bad function pointer");
_ClearScreen();
}
AsciiScreen::~AsciiScreen()
{
// delete [] _text; // Don't even bother
delete [] _foreground;
}
void AsciiScreen::Foreground(COLORREF foreground)
{
_cursorForeground = foreground;
}
// Goto - just updates the cursor position
void AsciiScreen::Goto(Pos & pos)
{
ASSERT(IsOnScreen(pos), "Cannot go off screen");
_cursor = pos;
}
// PutChar - puts char c at the current pos, and increments the
// cursor position
//
// c - char to put
// pos - position that this character was put at
//
// This is the fundamental put, where actual "writing to memory" happens
void AsciiScreen::Put(char c)
{
// if the buffer is full, give up--lose data
if (_inputBuffer.Length() >= ASBUFFER_LEN)
_inputBuffer.Clear();
_inputBuffer.Append(c); // Append string to buffer
// Scan for escape sequences
EscapeSequence seq(_inputBuffer);
if (seq.IsEscapeSequence())
{
if (seq.IsComplete()) // Got complete sequence
{
_inputBuffer.Clear();
_EscapeSequence(seq); // Do escape thingy (clears buffer)
};
}
else // Send the buffer directly to the console
{
for (int i = 0; i < _inputBuffer.Length(); i++)
{
char put_me = _inputBuffer[i];
// Check for "special characters"
if (put_me == '\r') // CR, no line feed!
_CarriageReturn();
else if (put_me == '\n')
_NewLine(1);
else if (put_me == '\010') // Backspace
_BackSpace();
else
{
_TextElement(_cursor) = put_me;
_ForegroundElement(_cursor) = _cursorForeground;
_IncrementPos(); // Just put a char, move the cursor
};
};
_inputBuffer.Clear();
};
}
// PutString - puts an entire string on the display
void AsciiScreen::Put(char * c)
{
ASSERT(NULL != c, "Null string pointer?");
// Copy string into memory one char at a time.
int len = strlen(c);
for (int i = 0; i < len; i++)
Put(c[i]);
}
// ------------------------------------------------------------------------
// Resize - resizes the screen buffer
//
// Does not attempt to preserve the contents.
//
// Throws:
// rethrows xalloc - in this case, the window was NOT resized, but
// the contents are still valid, and everything is cool!
//
void AsciiScreen::Resize(int width, int height)
{
char * new_text = NULL;
COLORREF * new_fg;
try
{
new_text = new char[width * height];
new_fg = new COLORREF[width * height];
}
catch (xalloc &) // New failed?
{
if (new_text) // Maybe this was successfully allocated
delete new_text;
throw; // Pass the buck
}
delete [] _text; // Success!
delete [] _foreground;
_text = new_text;
_foreground = new_fg;
_width = width;
_height = height;
_scrollRegionTop = 0;
_scrollRegionBottom = height - 1;
_cursor.X() = 0;
_cursor.Y() = 0;
_ClearScreen();
}
// Scroll - Scrolls the indicated range the indicated amount
//
// Note that a newline actually scrolls the "current window" area.
// Note that the internal text data array is up-to-date at the time
// of the call to the scrollfunc.
//
// Parameters:
// top - top of the area to scroll
// bottom - bottom of the area to scroll
// range - amount to scroll (may be negative)
void AsciiScreen::Scroll(int top, int bottom, int amount)
{
ASSERT(bottom >= top, "Nothing to scroll");
ASSERT(top >= 0, "Top off screen?");
ASSERT(bottom < Height(), "Bottom off screen?");
int i; // A counter
int too_big_just_clear = 0;
// Move the region up or down. Just lose the stuff that scrolls
// out of the region.
if (0 < amount) // Scroll forward
{
if (amount > (bottom - top + 1))
{
_ClearRows(top, bottom);
too_big_just_clear = 1;
}
else
{
// Copy rows
for (i = top; (i + amount) <= bottom; i++)
_CopyRow(i, i + amount);
// Clear everything that had no source for copying
for (i = (bottom - amount + 1); i <= bottom; i++)
_ClearRow(i);
};
}
else // Scroll back (amount is negative)
{
if ((-amount) > (bottom - top + 1))
{
_ClearRows(top, bottom);
too_big_just_clear = 1;
}
else
{
for (i = bottom; (i + amount) >= top; i--)
_CopyRow(i, i + amount);
for (i = top; i < (top - amount); i++)
_ClearRow(i);
};
};
// Now that the memory is updated, update the screen
if (too_big_just_clear) // Everything scrolled away?
_ClearRows(top, bottom);
else
{
// Try to scroll the screen by calling the callback. If this fails,
// invalidate the area we tried to scroll.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -